From 4b73e86b1f455e8ae19f8763662ade199aa9ebfc Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 22 Mar 2023 22:35:01 -0700 Subject: [PATCH 01/46] Some long-needed renaming This commit takes a first stab at some holistic renaming of internal concepts. I'm going to take another stab at what this commit calls "SubscriptionTarget" before submitting the PR (I think it's overly narrow), but the overall cleanups here are good. This commit also takes a step toward cleaning up and clarifying the implementation of subscriptions. More to come. --- .config/tsconfig/tsconfig.shared.json | 5 +- .vscode/settings.json | 8 +- @types/ansicolor/.eslintrc.json | 12 + @types/ansicolor/.npmrc | 2 + @types/ansicolor/index.d.ts | 44 + @types/ansicolor/package.json | 30 + @types/ansicolor/tsconfig.json | 12 + package.json | 66 +- packages/preact/preact-utils/index.ts | 2 + packages/preact/preact-utils/src/plugin.ts | 2 +- packages/preact/preact/src/frame.ts | 6 +- packages/preact/preact/src/options.ts | 6 +- packages/react/react/package.json | 3 +- packages/react/react/src/context-provider.ts | 2 +- packages/react/react/src/debug/warnings.ts | 4 +- packages/react/react/src/element.ts | 17 +- packages/react/react/src/use-resource.ts | 8 +- packages/react/react/tests/package.json | 5 +- packages/react/test-utils/package.json | 3 +- packages/react/test-utils/src/modes.ts | 4 +- packages/universal/debug/package.json | 1 + .../universal/debug/src/component/stack.ts | 10 +- .../universal/debug/src/description/impl.ts | 6 +- packages/universal/debug/src/timeline.ts | 68 +- packages/universal/interfaces/index.d.ts | 13 +- .../interfaces/src/debug-protocol/tree.d.ts | 8 +- .../universal/interfaces/src/description.d.ts | 2 +- packages/universal/interfaces/src/frame.d.ts | 41 +- .../universal/interfaces/src/protocol.d.ts | 72 +- packages/universal/interfaces/src/utils.d.ts | 1 + packages/universal/js/src/collection.ts | 4 +- packages/universal/modifier/src/modifier.ts | 4 +- packages/universal/timeline/index.ts | 16 +- .../universal/timeline/src/timeline/frame.ts | 84 +- .../universal/timeline/src/timeline/frames.ts | 135 +- .../timeline/src/timeline/protocol.ts | 230 +- .../timeline/src/timeline/subscriptions.md | 84 + .../timeline/src/timeline/subscriptions.ts | 306 ++- .../timeline/src/timeline/timeline.ts | 95 +- .../universal/timeline/tests/consume.spec.ts | 18 +- .../universal/timeline/tests/pollable.spec.ts | 30 +- .../universal/timeline/tests/protocol.spec.ts | 56 +- .../universal/timeline/tests/subscription.ts | 43 +- .../timeline/tests/support/mini-reactives.ts | 174 +- packages/universal/universal/index.ts | 10 +- .../universal/src/reactive-core/cell.ts | 11 +- .../universal/src/reactive-core/delegate.ts | 24 +- .../src/reactive-core/formula/formula.ts | 26 +- .../reactive-core/formula/polled-formula.ts | 20 +- .../higher-level/resource-list.ts | 8 +- .../universal/src/reactive-core/marker.ts | 12 +- .../universal/src/reactive-core/reactive.ts | 8 +- .../src/reactive-core/resource/resource.ts | 22 +- .../src/reactive-core/resource/run.ts | 4 +- .../src/reactive-core/resource/state.ts | 25 +- .../universal/src/reactive-core/variants.ts | 23 +- packages/universal/universal/src/storage.ts | 23 +- .../universal/universal/tests/factory.spec.ts | 4 +- .../universal/universal/tests/setup.spec.ts | 22 +- .../universal/tests/variants.spec.ts | 8 +- pnpm-lock.yaml | 2410 ++++++++++------- workspace/build/package.json | 8 +- workspace/eslint/package.json | 20 +- workspace/eslint/src/base.js | 4 +- workspace/eslint/src/esm.js | 4 +- workspace/eslint/tsconfig.json | 3 +- 66 files changed, 2530 insertions(+), 1911 deletions(-) create mode 100644 @types/ansicolor/.eslintrc.json create mode 100644 @types/ansicolor/.npmrc create mode 100644 @types/ansicolor/index.d.ts create mode 100644 @types/ansicolor/package.json create mode 100644 @types/ansicolor/tsconfig.json create mode 100644 packages/universal/interfaces/src/utils.d.ts create mode 100644 packages/universal/timeline/src/timeline/subscriptions.md diff --git a/.config/tsconfig/tsconfig.shared.json b/.config/tsconfig/tsconfig.shared.json index 1a48b232..f0eae030 100644 --- a/.config/tsconfig/tsconfig.shared.json +++ b/.config/tsconfig/tsconfig.shared.json @@ -4,7 +4,7 @@ "target": "ESNext", "module": "ESNext", - "moduleResolution": "Node", + "moduleResolution": "bundler", "declaration": true, "declarationMap": true, @@ -17,7 +17,6 @@ "noImplicitOverride": true, "isolatedModules": true, - "preserveValueImports": true, "skipLibCheck": true, "skipDefaultLibCheck": true, @@ -25,7 +24,7 @@ "allowSyntheticDefaultImports": true, "useDefineForClassFields": true, - "importsNotUsedAsValues": "error", + "verbatimModuleSyntax": true, "resolveJsonModule": true, diff --git a/.vscode/settings.json b/.vscode/settings.json index c309c0dc..58734b2f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -39,7 +39,7 @@ "html" ], - "explorer.excludeGitIgnore": false, + "explorer.excludeGitIgnore": true, "explorer.fileNesting.patterns": { "*.cjs": "${capture}.cjs.map, ${capture}.min.cjs, ${capture}.d.cts, ${capture}.d.cts.map", "*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.d.ts.map", @@ -68,6 +68,7 @@ "url": "https://json.schemastore.org/chrome-manifest" } ], + "npm-scripts.showStartNotification": false, "search.exclude": { "**/CHANGELOG.md": true, @@ -77,9 +78,10 @@ "testing.automaticallyOpenPeekView": "never", "typescript.preferences.importModuleSpecifier": "project-relative", - "typescript.preferences.importModuleSpecifierEnding": "js", + "typescript.preferences.importModuleSpecifierEnding": "auto", "typescript.tsdk": "node_modules/typescript/lib", "typescript.tsserver.experimental.enableProjectDiagnostics": true, - "vitest.enable": true + "vitest.enable": true, + "typescript.experimental.tsserver.web.enableProjectWideIntellisense": true } diff --git a/@types/ansicolor/.eslintrc.json b/@types/ansicolor/.eslintrc.json new file mode 100644 index 00000000..417a9ee9 --- /dev/null +++ b/@types/ansicolor/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/commonjs"], + "files": ["index.d.ts", "src/**/*.d.ts"], + "parserOptions": { + "project": "@types/ansicolor/tsconfig.json" + } + } + ] +} diff --git a/@types/ansicolor/.npmrc b/@types/ansicolor/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/@types/ansicolor/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/@types/ansicolor/index.d.ts b/@types/ansicolor/index.d.ts new file mode 100644 index 00000000..b2fe0a25 --- /dev/null +++ b/@types/ansicolor/index.d.ts @@ -0,0 +1,44 @@ +type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; + +type Colors = + | "Black" + | "Red" + | "Green" + | "Yellow" + | "Blue" + | "Magenta" + | "Cyan" + | "White" + | "Default"; + +type Styles = "bright" | "dim" | "italic" | "underline" | "inverse"; + +type Bg = `bg${"Bright" | ""}${Colors}`; + +type BgColor = Expand<{ + [key in Colors]: Color; +}>; + +type FgColor = Expand<{ + bright: Color; + dim: Color; + italic: Color; + underline: Color; + inverse: Color; + dim: Color; + magenta: Color; + black: Color; + red: Color; + green: Color; + yellow: Color; + blue: Color; + magenta: Color; + cyan: Color; + white: Color; + default: Color; +}>; + +type Color = BgColor & FgColor & ((text: string) => string); + +const DEFAULT: Color; +export default DEFAULT; diff --git a/@types/ansicolor/package.json b/@types/ansicolor/package.json new file mode 100644 index 00000000..2a0617e6 --- /dev/null +++ b/@types/ansicolor/package.json @@ -0,0 +1,30 @@ +{ + "private": true, + "name": "@types/ansicolor", + "version": "1.0.0", + "types": "index.d.ts", + "exports": { + ".": { + "types": "./index.d.ts" + } + }, + "publishConfig": { + "exports": { + ".": { + "types": "./dist/index.d.ts" + } + }, + "types": "dist/index.d.ts" + }, + "starbeam": { + "source": "d.ts", + "type": "library:upstream-types" + }, + "scripts": { + "test:lint": "eslint", + "test:types": "tsc -b" + }, + "devDependencies": { + "@types/node": "*" + } +} diff --git a/@types/ansicolor/tsconfig.json b/@types/ansicolor/tsconfig.json new file mode 100644 index 00000000..0526e14e --- /dev/null +++ b/@types/ansicolor/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "declarationMap": true, + "declarationDir": "../../dist/types", + "declaration": true, + "outDir": "../../dist/packages", + "composite": true, + "types": ["../../packages/env", "node"] + }, + "exclude": ["dist/**/*"] +} diff --git a/package.json b/package.json index a5f0d2f8..8f7fb966 100644 --- a/package.json +++ b/package.json @@ -105,44 +105,42 @@ "@starbeam/core-utils": "workspace:^0.8.9" }, "devDependencies": { - "@babel/eslint-parser": "^7.19.1", - "@babel/plugin-proposal-decorators": "^7.20.7", + "@babel/eslint-parser": "^7.21.3", + "@babel/plugin-proposal-decorators": "^7.21.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.19.6", + "@babel/plugin-transform-runtime": "^7.21.0", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@babel/runtime": "^7.20.7", + "@babel/preset-typescript": "^7.21.0", + "@babel/runtime": "^7.21.0", "@changesets/changelog-git": "^0.1.14", - "@changesets/cli": "^2.26.0", + "@changesets/cli": "^2.26.1", "@changesets/config": "^2.3.0", "@starbeam/eslint-plugin": "workspace:^1.0.0", "@starbeam-dev/build-support": "workspace:1.0.0", - "@types/eslint": "^8.4.10", - "@types/node": "18.11.18", - "@typescript-eslint/eslint-plugin": "^5.48.0", - "@typescript-eslint/parser": "^5.48.0", - "@vitest/ui": "^0.26.3", - "eslint": "^8.31.0", + "@types/eslint": "^8.21.3", + "@types/node": "18.15.5", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", + "@vitest/ui": "^0.29.7", + "eslint": "^8.36.0", "eslint-config-airbnb": "^19.0.4", - "eslint-config-prettier": "^8.6.0", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsonc": "^2.5.0", + "eslint-config-prettier": "^8.8.0", + "eslint-import-resolver-typescript": "^3.5.3", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jsonc": "^2.7.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-simple-import-sort": "^8.0.0", + "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^2.0.0", "esno": "^0.16.3", "fast-glob": "^3.2.12", - "happy-dom": "^8.1.1", - "jsdom": "^20.0.3", - "lint-to-the-future": "^1.3.1", - "lint-to-the-future-eslint": "^1.0.1", - "prettier": "^2.8.1", - "tslib": "^2.4.1", - "typescript": "^4.9.4", - "vite": "4.0.4", - "vitest": "0.26.3" + "happy-dom": "^8.9.0", + "jsdom": "^21.1.1", + "prettier": "^2.8.6", + "tslib": "^2.5.0", + "typescript": "^5.0.2", + "vite": "4.2.1", + "vitest": "0.29.7" }, "license": "MIT", "nodemonConfig": { @@ -156,18 +154,16 @@ "overrides": { "@rollup/plugin-commonjs": "^24.0.0", "@rollup/plugin-node-resolve": "^15.0.1", - "@types/eslint": "^8.4.10", - "@types/node": "18.11.18", - "@typescript-eslint/eslint-plugin": "^5.48.0", - "@typescript-eslint/parser": "^5.48.0", - "@vitest/ui": "^0.26.3", - "eslint": "^8.31.0", + "@types/eslint": "$@types/eslint", + "@types/node": "$@types/node", + "@typescript-eslint/eslint-plugin": "$@typescript-eslint/eslint-plugin", + "@typescript-eslint/parser": "$@typescript-eslint/parser", + "eslint": "$eslint", "preact": "^10.11.3", "rollup": "^3.9.1", - "typescript": "^4.9.4", - "vite": "4.0.4", + "typescript": "$typescript", + "vite": "$vite", "vite-plugin-fonts": "0.7.0", - "vitest": "0.26.3", "vue": "^3.2.39" }, "peerDependencyRules": { diff --git a/packages/preact/preact-utils/index.ts b/packages/preact/preact-utils/index.ts index e6838db1..8f4128b3 100644 --- a/packages/preact/preact-utils/index.ts +++ b/packages/preact/preact-utils/index.ts @@ -1,4 +1,6 @@ export { implementInspect } from "./src/debug.js"; +export type { RawPreactOptions } from "./src/interfaces.js"; export { InternalComponent } from "./src/internals/component.js"; +export { InternalElement } from "./src/internals/elements.js"; export { InternalVNode } from "./src/internals/vnode.js"; export { AugmentPreact, Plugin } from "./src/plugin.js"; diff --git a/packages/preact/preact-utils/src/plugin.ts b/packages/preact/preact-utils/src/plugin.ts index 8b49ca75..04754982 100644 --- a/packages/preact/preact-utils/src/plugin.ts +++ b/packages/preact/preact-utils/src/plugin.ts @@ -2,10 +2,10 @@ import type { Options } from "preact"; import type { AnyFn, RawPreactOptions } from "./interfaces.js"; import { + isProbablyVNode, type MangledPreactOptionName, type PreactHook, type PreactOptionName, - isProbablyVNode, } from "./internals.js"; import { InternalComponent } from "./internals/component.js"; import { InternalElement } from "./internals/elements.js"; diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index 39678d55..e952c140 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -4,8 +4,8 @@ import type { InternalComponent } from "@starbeam/preact-utils"; import { type ActiveFrame, type Frame, - type Unsubscribe, TIMELINE, + type Unsubscribe, } from "@starbeam/timeline"; import { expected, isPresent, verify } from "@starbeam/verify"; @@ -79,9 +79,9 @@ export class ComponentFrame { #start(description: Description): void { if (this.#frame) { - this.#active = TIMELINE.frame.update({ updating: this.#frame }); + this.#active = TIMELINE.frame.update(this.#frame); } else { - this.#active = TIMELINE.frame.create({ + this.#active = TIMELINE.frame.open({ description, }); } diff --git a/packages/preact/preact/src/options.ts b/packages/preact/preact/src/options.ts index 8e482d8e..d9fbfcb4 100644 --- a/packages/preact/preact/src/options.ts +++ b/packages/preact/preact/src/options.ts @@ -1,7 +1,9 @@ import { descriptionFrom } from "@starbeam/debug"; -import type { InternalComponent } from "@starbeam/preact-utils"; +import type { + InternalComponent, + InternalElement, +} from "@starbeam/preact-utils"; import { Plugin } from "@starbeam/preact-utils"; -import type { InternalElement } from "@starbeam/preact-utils/src/internals/elements.js"; import { CONTEXT, LIFETIME, Reactive } from "@starbeam/timeline"; import type { ComponentType } from "preact"; diff --git a/packages/react/react/package.json b/packages/react/react/package.json index 5f72dcde..b4c46555 100644 --- a/packages/react/react/package.json +++ b/packages/react/react/package.json @@ -42,7 +42,8 @@ "devDependencies": { "@domtree/flavors": "workspace:^", "@starbeam-dev/build-support": "workspace:*", - "@types/react": "^18.0.26" + "@types/node": "^18.15.5", + "@types/react": "^18.0.28" }, "peerDependencies": { "react": "^18.2.0", diff --git a/packages/react/react/src/context-provider.ts b/packages/react/react/src/context-provider.ts index 2b6cd1f6..2507c371 100644 --- a/packages/react/react/src/context-provider.ts +++ b/packages/react/react/src/context-provider.ts @@ -2,9 +2,9 @@ import { LIFETIME } from "@starbeam/timeline"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; import type { FunctionComponent } from "react"; import { - type PropsWithChildren, createContext, createElement, + type PropsWithChildren, useContext, } from "react"; diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index 64869048..8d219558 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,5 +1,5 @@ import { Message } from "@starbeam/debug"; -import { ReactiveProtocol, TIMELINE } from "@starbeam/timeline"; +import { SubscriptionTarget, TIMELINE } from "@starbeam/timeline"; import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; @@ -10,7 +10,7 @@ if (import.meta.env.DEV) { if (!WARNED) { WARNED = true; - const description = ReactiveProtocol.description(reactive).userFacing; + const description = SubscriptionTarget.description(reactive).userFacing; const caller = stack.caller; const pad = Math.max( diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 2d4e1c51..c373d1ee 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,19 +1,19 @@ import type { browser } from "@domtree/flavors"; -import { type DebugListener, type Description, Desc } from "@starbeam/debug"; +import { type DebugListener, Desc, type Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; +import type { SubscriptionTarget } from "@starbeam/timeline"; import { type CleanupTarget, - type OnCleanup, - type ReactiveProtocol, - type Unsubscribe, LIFETIME, + type OnCleanup, TIMELINE, + type Unsubscribe, } from "@starbeam/timeline"; import { type Cell, - type IntoResource, createService, Factory, + type IntoResource, } from "@starbeam/universal"; import { ReactApp } from "./context-provider.js"; @@ -128,7 +128,7 @@ class Refs { export type DebugLifecycle = ( listener: DebugListener, - reactive: ReactiveProtocol + reactive: SubscriptionTarget ) => () => void; /** @@ -201,7 +201,10 @@ export class ReactiveElement implements CleanupTarget { element.#lifecycle = Lifecycle.create(element.#description); } - static subscribe(element: ReactiveElement, reactive: ReactiveProtocol): void { + static subscribe( + element: ReactiveElement, + reactive: SubscriptionTarget + ): void { const subscription = TIMELINE.on.change(reactive, element.notify); element.on.cleanup(subscription); } diff --git a/packages/react/react/src/use-resource.ts b/packages/react/react/src/use-resource.ts index af835f82..8a771643 100644 --- a/packages/react/react/src/use-resource.ts +++ b/packages/react/react/src/use-resource.ts @@ -1,12 +1,12 @@ -import { type Description, Desc } from "@starbeam/debug"; +import { Desc, type Description } from "@starbeam/debug"; import { LIFETIME, TIMELINE } from "@starbeam/timeline"; import { - type IntoResource, - type Reactive, - type ResourceBlueprint, Cell, Factory, Formula, + type IntoResource, + type Reactive, + type ResourceBlueprint, Wrap, } from "@starbeam/universal"; import { diff --git a/packages/react/react/tests/package.json b/packages/react/react/tests/package.json index 427bf930..cd3818fd 100644 --- a/packages/react/react/tests/package.json +++ b/packages/react/react/tests/package.json @@ -15,7 +15,8 @@ "@starbeam/universal": "workspace:^", "@starbeam-workspace/react-test-utils": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", - "jsdom": "^20.0.3", - "react": "^18" + "jsdom": "^21.1.1", + "react": "^18.2.0", + "vitest": "*" } } diff --git a/packages/react/test-utils/package.json b/packages/react/test-utils/package.json index dbbee3d5..9054e3f9 100644 --- a/packages/react/test-utils/package.json +++ b/packages/react/test-utils/package.json @@ -24,13 +24,14 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/verify": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^" }, "devDependencies": { "@starbeam-dev/build-support": "workspace:*", - "@testing-library/react": "latest", + "@testing-library/react": "^14.0.0", "@types/react": "^18.0.26" }, "peerDependencies": { diff --git a/packages/react/test-utils/src/modes.ts b/packages/react/test-utils/src/modes.ts index cd40248b..2dab37e4 100644 --- a/packages/react/test-utils/src/modes.ts +++ b/packages/react/test-utils/src/modes.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { getLast, isPresentArray } from "@starbeam/core-utils"; -import { type Stack, callerStack, entryPoint } from "@starbeam/debug"; -import { type TestAPI, expect, test } from "@starbeam-workspace/test-utils"; +import { callerStack, entryPoint, type Stack } from "@starbeam/debug"; +import { expect, test, type TestAPI } from "@starbeam-workspace/test-utils"; import * as testing from "@testing-library/react"; import { getByRole, getByText } from "@testing-library/react"; import { type ReactElement, StrictMode } from "react"; diff --git a/packages/universal/debug/package.json b/packages/universal/debug/package.json index f94bb994..7dada9fb 100644 --- a/packages/universal/debug/package.json +++ b/packages/universal/debug/package.json @@ -47,6 +47,7 @@ }, "devDependencies": { "@starbeam-dev/build-support": "workspace:*", + "@types/ansicolor": "workspace:^", "@types/node": "^18.7.23" }, "pnpm": { diff --git a/packages/universal/debug/src/component/stack.ts b/packages/universal/debug/src/component/stack.ts index 74da1547..ba50d844 100644 --- a/packages/universal/debug/src/component/stack.ts +++ b/packages/universal/debug/src/component/stack.ts @@ -22,17 +22,17 @@ export interface Component { lifecycle: (timing: "layout" | "idle") => Lifecycle; ref: (description: interfaces.Description) => Ref; modifier: (timing: "layout" | "idle") => Modifier; - resource: (reactive: interfaces.ReactiveProtocol) => interfaces.Unsubscribe; + resource: (reactive: interfaces.SubscriptionTarget) => interfaces.Unsubscribe; domResource: ( timing: "layout" | "idle", - reactive: interfaces.ReactiveProtocol + reactive: interfaces.SubscriptionTarget ) => interfaces.Unsubscribe; } export interface Lifecycle { setup: ( timing: "layout" | "idle", - protocol: interfaces.ReactiveProtocol + protocol: interfaces.SubscriptionTarget ) => interfaces.Unsubscribe; } @@ -108,7 +108,7 @@ if (import.meta.env.DEV) { } domResource( _timing: "layout" | "idle", - _reactive: interfaces.ReactiveProtocol + _reactive: interfaces.SubscriptionTarget ): interfaces.Unsubscribe { throw new Error("Method not implemented."); } @@ -121,7 +121,7 @@ if (import.meta.env.DEV) { ref(_description: interfaces.Description): Ref { throw new Error("Method not implemented."); } - resource(_reactive: interfaces.ReactiveProtocol): interfaces.Unsubscribe { + resource(_reactive: interfaces.SubscriptionTarget): interfaces.Unsubscribe { throw new Error("Method not implemented."); } } diff --git a/packages/universal/debug/src/description/impl.ts b/packages/universal/debug/src/description/impl.ts index 7fd71f75..b12d56dc 100644 --- a/packages/universal/debug/src/description/impl.ts +++ b/packages/universal/debug/src/description/impl.ts @@ -5,7 +5,7 @@ import ansicolor from "ansicolor"; import { DisplayStruct } from "../inspect/display-struct.js"; import { DisplayParts } from "../module.js"; -import { type Stack, callerStack } from "../stack.js"; +import { callerStack, type Stack } from "../stack.js"; /** * This symbol is used in APIs that accept an ID to indicate that an existing ID should be reused. @@ -284,7 +284,9 @@ if (import.meta.env.DEV) { detail( this: DebugDescription, name: string, - args?: string[] | { args?: string[]; note?: string; id?: string | number } + args?: + | string[] + | { args?: string[]; note?: string; id?: interfaces.ReactiveId } ): interfaces.Description { let detailArgs: string[] | undefined; let note: string | undefined; diff --git a/packages/universal/debug/src/timeline.ts b/packages/universal/debug/src/timeline.ts index 9d4c20fe..86627bc4 100644 --- a/packages/universal/debug/src/timeline.ts +++ b/packages/universal/debug/src/timeline.ts @@ -1,25 +1,25 @@ import type { - CompositeInternals, + CellCore, Diff, + FormulaCore, Frame, - MutableInternals, - ReactiveInternals, - ReactiveProtocol, + ReactiveCore, Stack, + SubscriptionTarget, Timestamp, } from "@starbeam/interfaces"; import { REACTIVE } from "@starbeam/shared"; import { exhaustive } from "@starbeam/verify"; -interface ReactiveProtocolStatics { - dependencies: (reactive: ReactiveProtocol) => Iterable; +interface SubscriptionTargetStatics { + dependencies: (reactive: SubscriptionTarget) => Iterable; } -function reactiveInternals(reactive: ReactiveProtocol): ReactiveInternals { +function reactiveInternals(reactive: SubscriptionTarget): ReactiveCore { return reactive[REACTIVE]; } -interface OperationInfo { +interface OperationInfo { readonly at: Timestamp; readonly for: I; readonly caller: Stack; @@ -30,7 +30,7 @@ export type DebugOperationOptions = | CellUpdateOperation | FrameConsumeOperation; -export class LeafOperation { +export class LeafOperation { #data: OperationInfo; constructor(data: OperationInfo) { @@ -50,21 +50,21 @@ export class LeafOperation { } } -export class CellConsumeOperation extends LeafOperation { +export class CellConsumeOperation extends LeafOperation { readonly type = "cell:consume"; } -export class CellUpdateOperation extends LeafOperation { +export class CellUpdateOperation extends LeafOperation { readonly type = "cell:update"; } -interface FrameConsumeInfo extends OperationInfo { - readonly diff: Diff; +interface FrameConsumeInfo extends OperationInfo { + readonly diff: Diff; readonly frame: Frame; } -export class FrameConsumeOperation extends LeafOperation { - readonly #diff: Diff; +export class FrameConsumeOperation extends LeafOperation { + readonly #diff: Diff; readonly #frame: Frame; readonly type = "frame:consume"; @@ -74,7 +74,7 @@ export class FrameConsumeOperation extends LeafOperation { this.#frame = data.frame; } - get diff(): Diff { + get diff(): Diff { return this.#diff; } @@ -86,7 +86,7 @@ export class MutationLog { readonly type = "mutation"; // This makes `DebugOperation.for` ==== `ReactiveInternals | undefined`, which makes it possible // to easily compare the `for` value without a lot of extra type shenanigans. - readonly for: ReactiveInternals | undefined = undefined; + readonly for: ReactiveCore | undefined = undefined; readonly #at: Timestamp; #description: string; @@ -116,19 +116,19 @@ export type DebugOperation = export interface Flush { readonly history: DebugOperation[]; - for: (reactive: ReactiveProtocol) => readonly DebugOperation[]; + for: (reactive: SubscriptionTarget) => readonly DebugOperation[]; } export type DebugListener = InstanceType; export type DebugFilter = - | { type: "by-reactive"; reactive: ReactiveProtocol } + | { type: "by-reactive"; reactive: SubscriptionTarget } | { type: "all" } | { type: "none" }; function filterToPredicate( filter: DebugFilter, - reactive: ReactiveProtocolStatics + reactive: SubscriptionTargetStatics ): ((operation: DebugOperation) => boolean) | undefined { switch (filter.type) { case "by-reactive": { @@ -161,7 +161,7 @@ const INITIAL_OFFSET = 0; export class DebugTimeline { #timestamp: { now: () => Timestamp }; - #statics: ReactiveProtocolStatics; + #statics: SubscriptionTargetStatics; #trimOffset = INITIAL_OFFSET; #operationList: DebugOperation[] = []; #currentMutation: MutationLog | null = null; @@ -170,7 +170,7 @@ export class DebugTimeline { static Flush = class Flush { constructor(readonly history: DebugOperation[]) {} - for(reactive: ReactiveProtocol): DebugOperation[] { + for(reactive: SubscriptionTarget): DebugOperation[] { const internals = reactiveInternals(reactive); return this.history.filter((item) => item.for === internals); } @@ -198,7 +198,7 @@ export class DebugTimeline { static create( timestamp: { now: () => Timestamp }, - statics: ReactiveProtocolStatics + statics: SubscriptionTargetStatics ): DebugTimeline { return new DebugTimeline(timestamp, statics); } @@ -229,14 +229,14 @@ export class DebugTimeline { static create( timestamp: { now: () => Timestamp }, - statics: ReactiveProtocolStatics + statics: SubscriptionTargetStatics ): DebugTimeline { return new DebugTimeline(timestamp, statics); } private constructor( timestamp: { now: () => Timestamp }, - statics: ReactiveProtocolStatics + statics: SubscriptionTargetStatics ) { this.#timestamp = timestamp; this.#statics = statics; @@ -296,7 +296,7 @@ export class DebugTimeline { } } - #consumeCell(cell: MutableInternals, caller: Stack): void { + #consumeCell(cell: CellCore, caller: Stack): void { this.#add( new CellConsumeOperation({ at: this.#timestamp.now(), @@ -306,19 +306,15 @@ export class DebugTimeline { ); } - consumeCell(internals: MutableInternals, caller: Stack): void { + consumeCell(internals: CellCore, caller: Stack): void { this.#consumeCell(internals, caller); } - consumeFrame( - frame: Frame, - diff: Diff, - caller: Stack - ): void { + consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { this.#consumeFrame(frame, diff, caller); } - updateCell(cell: MutableInternals, caller: Stack): void { + updateCell(cell: CellCore, caller: Stack): void { this.#add( new CellUpdateOperation({ at: this.#timestamp.now(), @@ -328,11 +324,7 @@ export class DebugTimeline { ); } - #consumeFrame( - frame: Frame, - diff: Diff, - caller: Stack - ): void { + #consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { this.#add( new FrameConsumeOperation({ at: this.#timestamp.now(), diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index b480cd75..daa4b9fa 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -25,16 +25,16 @@ export type { ValidFrame, } from "./src/frame.js"; export type { - CompositeInternals, - DelegateInternals, - MutableInternals, + CellCore, + DelegateCore, + FormulaCore, Reactive, ReactiveCell, ReactiveCore, ReactiveId, - ReactiveInternals, - ReactiveProtocol, - StaticInternals, + ReactiveValue, + StaticCore, + SubscriptionTarget, } from "./src/protocol.js"; export type { DisplayParts, @@ -43,3 +43,4 @@ export type { StackFrameDisplayOptions, } from "./src/stack.js"; export type { Timestamp, TimestampStatics } from "./src/timestamp.js"; +export type { Expand } from "./src/utils.js"; diff --git a/packages/universal/interfaces/src/debug-protocol/tree.d.ts b/packages/universal/interfaces/src/debug-protocol/tree.d.ts index c305be5b..87a5796d 100644 --- a/packages/universal/interfaces/src/debug-protocol/tree.d.ts +++ b/packages/universal/interfaces/src/debug-protocol/tree.d.ts @@ -1,7 +1,7 @@ import type * as anydom from "@domtree/any"; import type { Description } from "../description.js"; -import type { ReactiveProtocol } from "../protocol.js"; +import type { SubscriptionTarget } from "../protocol.js"; export interface INode { readonly type: string; @@ -52,7 +52,7 @@ export interface ComponentNode extends INode { export interface LifecyclePart extends INode { readonly type: "lifecycle"; readonly timing: "layout" | "idle"; - readonly setups: ReactiveProtocol[]; + readonly setups: SubscriptionTarget[]; } export interface RefPart extends INode { @@ -69,12 +69,12 @@ export interface ModifierPart extends INode { export interface DomResourcePart extends INode { readonly type: "resource:dom"; readonly timing: "layout" | "idle"; - readonly reactive: ReactiveProtocol; + readonly reactive: SubscriptionTarget; } export interface ResourcePart extends INode { readonly type: "resource"; - readonly reactive: ReactiveProtocol; + readonly reactive: SubscriptionTarget; } export type ComponentPart = diff --git a/packages/universal/interfaces/src/description.d.ts b/packages/universal/interfaces/src/description.d.ts index 19f5c8f4..831e2414 100644 --- a/packages/universal/interfaces/src/description.d.ts +++ b/packages/universal/interfaces/src/description.d.ts @@ -92,7 +92,7 @@ export interface Description extends DescriptionArgs { */ detail: ( name: string, - args?: string[] | { args?: string[]; note?: string; id?: string | number } + args?: string[] | { args?: string[]; note?: string; id?: ReactiveId } ) => Description; implementation: ( id: ReactiveId | symbol, diff --git a/packages/universal/interfaces/src/frame.d.ts b/packages/universal/interfaces/src/frame.d.ts index 52952896..dcc7765c 100644 --- a/packages/universal/interfaces/src/frame.d.ts +++ b/packages/universal/interfaces/src/frame.d.ts @@ -1,7 +1,7 @@ import type { UNINITIALIZED } from "@starbeam/shared"; import type { Description } from "./description.js"; -import type { CompositeInternals, ReactiveProtocol } from "./protocol.js"; +import type { FormulaCore, SubscriptionTarget } from "./protocol.js"; export interface ValidFrame { readonly status: "valid"; @@ -15,45 +15,8 @@ export interface InvalidFrame { export type FrameValidation = ValidFrame | InvalidFrame; export interface Frame<_T = unknown> - extends ReactiveProtocol { + extends SubscriptionTarget { readonly description: Description; validate: () => FrameValidation>; - - // update( - // this: Frame, - // value: U, - // children: Set, - // finalized: Timestamp - // ): Frame; - // update( - // value: T, - // children: Set, - // finalized: Timestamp - // ): Frame; - // update( - // value: T, - // children: Set, - // finalized: Timestamp - // ): Frame { - // if (Object.is(this.#value, UNINITIALIZED)) { - // this.#initialized[REACTIVE].lastUpdated = finalized; - // } - - // this.#value = value; - // this.#children = children; - // this.#finalized = finalized; - // return this; - // } - - // validate(this: Frame): FrameValidation { - // if ( - // Object.is(this.#value, UNINITIALIZED) || - // ReactiveProtocol.lastUpdatedIn([...this.#children]).gt(this.#finalized) - // ) { - // return { status: "invalid" }; - // } else { - // return { status: "valid", value: this.#value as U }; - // } - // } } diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 81f1facd..277be4f6 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -6,55 +6,85 @@ import type { Timestamp } from "./timestamp.js"; export type ReactiveId = number | string | ReactiveId[]; -interface Internals { +interface Core { readonly type: string; readonly description: Description; } -export interface MutableInternals extends Internals { +/** + * Cell is the fundamental mutable reactive value. All subscriptions in Starbeam are ultimately + * subscriptions to cells, and all mutations in Starbeam are ultimately mutations to cells. + */ +export interface CellCore extends Core { readonly type: "mutable"; readonly lastUpdated: Timestamp; isFrozen?: () => boolean; } -export interface CompositeInternals extends Internals { +/** + * Formula is a reactive that has *dynamic* children. This means that you can't cache the children + * (or subscribe directly to them), because they may change. This is different from delegates, which + * are guaranteed to have the same set of children forever. + * + * Composite reactives must notify the timeline when their children have changed. + * + * A subscription to a composite reactive is a subscription to its current children, as of the last + * time the timeline was notified of changes to the composite's children. Whenever the timeline is + * notified of a change to the composite's children, it removes subscriptions from any stale + * dependencies and adds subscriptions to any new dependencies. + */ +export interface FormulaCore extends Core { readonly type: "composite"; - children: () => ReactiveProtocol[]; + children: () => SubscriptionTarget[]; } -export interface DelegateInternals extends Internals { +/** + * Delegate is a reactive that represents one or more reactives, but that set of reactives cannot + * change. This allows you to cache the value of the `delegate` property, and it also allows you to + * subscribe directly to the delegate's targets. + * + * In practice, when you subscribe to a delegate, the timeline subscribes directly to the delegate's + * targets. This means that delegates don't need to know when their value changes, and don't need to + * notify the timeline when their targets change. + */ +export interface DelegateCore extends Core { readonly type: "delegate"; - readonly delegate: readonly ReactiveProtocol[]; + readonly targets: readonly SubscriptionTarget[]; } -export interface StaticInternals extends Internals { +/** + * Static is a reactive that is guaranteed not to change. This means that you can cache the value of + * the static reactive and don't need to include it in composite children. All validation semantics + * act as if static reactives were not present. + * + * If a formula or delegate has only static children, it is also static. Even though a formula's + * children can change, if the formula's *only* children are static, then the formula can never + * invalidate, and therefore it, itself, is treated as static. + * + * TODO: Do we need a separate fundamental type for pollable formulas, which can get new + * dependencies even if they never invalidate? + */ +export interface StaticCore extends Core { readonly type: "static"; } -export type ReactiveInternals = - | MutableInternals - | CompositeInternals - | DelegateInternals - | StaticInternals; +export type ReactiveCore = CellCore | FormulaCore | DelegateCore | StaticCore; -export interface ReactiveProtocol< - I extends ReactiveInternals = ReactiveInternals -> { +export interface SubscriptionTarget { [REACTIVE]: I; } -export interface ReactiveCore< +export interface ReactiveValue< T = unknown, - I extends ReactiveInternals = ReactiveInternals -> extends ReactiveProtocol { + I extends ReactiveCore = ReactiveCore +> extends SubscriptionTarget { read: (stack?: Stack) => T; } -export interface Reactive - extends ReactiveCore { +export interface Reactive extends ReactiveValue { readonly current: T; } -export interface ReactiveCell extends Reactive { +export interface ReactiveCell extends Reactive { current: T; } diff --git a/packages/universal/interfaces/src/utils.d.ts b/packages/universal/interfaces/src/utils.d.ts new file mode 100644 index 00000000..1f4c4f9f --- /dev/null +++ b/packages/universal/interfaces/src/utils.d.ts @@ -0,0 +1 @@ +export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; diff --git a/packages/universal/js/src/collection.ts b/packages/universal/js/src/collection.ts index a66dfb46..71514a8c 100644 --- a/packages/universal/js/src/collection.ts +++ b/packages/universal/js/src/collection.ts @@ -1,5 +1,5 @@ import type { Description, Stack } from "@starbeam/debug"; -import { ReactiveProtocol } from "@starbeam/timeline"; +import { SubscriptionTarget } from "@starbeam/timeline"; import { Cell, Marker } from "@starbeam/universal"; import { expected, isPresent, verified } from "@starbeam/verify"; @@ -203,7 +203,7 @@ export class Collection { } let item: Item; - const iteration = ReactiveProtocol.description(this.#iteration); + const iteration = SubscriptionTarget.description(this.#iteration); if (disposition === "miss") { item = Item.uninitialized(iteration, member, caller); diff --git a/packages/universal/modifier/src/modifier.ts b/packages/universal/modifier/src/modifier.ts index 6aa9e068..38b56b29 100644 --- a/packages/universal/modifier/src/modifier.ts +++ b/packages/universal/modifier/src/modifier.ts @@ -1,6 +1,6 @@ import type { anydom } from "@domtree/flavors"; import { type Description, REUSE_ID } from "@starbeam/debug"; -import type { ReactiveProtocol } from "@starbeam/interfaces"; +import type { SubscriptionTarget } from "@starbeam/interfaces"; import { REACTIVE, UNINITIALIZED } from "@starbeam/shared"; import { Cell, DelegateInternals } from "@starbeam/universal"; import { expected, isPresent, verified, verify } from "@starbeam/verify"; @@ -14,7 +14,7 @@ export type ElementType = abstract new < // export type Ref = Initializable; export interface ElementPlaceholder - extends ReactiveProtocol { + extends SubscriptionTarget { readonly initialize: (value: E) => void; readonly current: E | null; } diff --git a/packages/universal/timeline/index.ts b/packages/universal/timeline/index.ts index b963cbe8..6fa25f73 100644 --- a/packages/universal/timeline/index.ts +++ b/packages/universal/timeline/index.ts @@ -1,29 +1,31 @@ // FIXME: Move the core of this to @starbeam/shared export { type ComponentContext, - type Context, CONTEXT, + type Context, } from "./src/context/context.js"; export { type CleanupTarget, + LIFETIME, type Lifetime, type OnCleanup, - LIFETIME, } from "./src/lifetime/api.js"; export type { Unsubscribe } from "./src/lifetime/object-lifetime.js"; export { TIMELINE } from "./src/timeline/api.js"; export { - type FrameValidation, ActiveFrame, Frame, + type FrameValidation, } from "./src/timeline/frame.js"; export { Reactive, - ReactiveCore, - ReactiveInternals, - ReactiveProtocol, + ReactiveCore as ReactiveInternals, + SubscriptionTarget, } from "./src/timeline/protocol.js"; -export { Subscription, Subscriptions } from "./src/timeline/subscriptions.js"; +export { + type NotifyReady, + Subscriptions, +} from "./src/timeline/subscriptions.js"; export { INSPECT } from "./src/timeline/timestamp.js"; export { max, getNow as now, zero } from "./src/timeline/timestamp.js"; export { diff } from "./src/timeline/utils.js"; diff --git a/packages/universal/timeline/src/timeline/frame.ts b/packages/universal/timeline/src/timeline/frame.ts index 7893a236..9496d893 100644 --- a/packages/universal/timeline/src/timeline/frame.ts +++ b/packages/universal/timeline/src/timeline/frame.ts @@ -1,44 +1,46 @@ import type { - CompositeInternals, + CellCore, Description, + FormulaCore, Frame as IFrame, - MutableInternals, - ReactiveId, Timestamp, } from "@starbeam/interfaces"; import { REACTIVE, UNINITIALIZED } from "@starbeam/shared"; +import { isNotEqual, verified } from "@starbeam/verify"; +import type { FrameStack } from "./frames.js"; import { getID } from "./id.js"; -import { ReactiveProtocol } from "./protocol.js"; +import { SubscriptionTarget } from "./protocol.js"; import type { Timeline } from "./timeline.js"; import { getNow } from "./timestamp.js"; interface Marker { - [REACTIVE]: Omit & { + [REACTIVE]: Omit & { lastUpdated: Timestamp; }; } export class Frame - implements ReactiveProtocol, IFrame + implements SubscriptionTarget, IFrame { static create( this: void, value: T, - children: Set, + children: Set, finalized: Timestamp, description: Description ): Frame { const id = getID(); return new Frame( - id, value, { [REACTIVE]: { type: "mutable", lastUpdated: finalized, - description: description.key("initialized?").asImplementation(), + description: description + .key("initialized?", { id }) + .asImplementation(), }, }, children, @@ -50,17 +52,16 @@ export class Frame static uninitialized( finalized: Timestamp, description: Description - ): Frame { + ): Frame { const id = description.id; - return new Frame( - id, + return new Frame( UNINITIALIZED, { [REACTIVE]: { type: "mutable", lastUpdated: finalized, - description: description.detail("initialized?"), + description: description.detail("initialized?", { id }), }, }, new Set(), @@ -70,7 +71,7 @@ export class Frame } static value(this: void, frame: Frame): T { - return frame.#value; + return verified(frame.#value, isNotEqual(UNINITIALIZED)); } static isInitialized(this: void, frame: Frame): boolean { @@ -81,7 +82,7 @@ export class Frame this: void, frame: Frame, value: T, - children: Set, + children: Set, finalized: Timestamp ): Frame { return frame.#update(value, children, finalized); @@ -90,26 +91,25 @@ export class Frame static updateChildren( this: void, frame: Frame, - children: Set + children: Set ): void { frame.#children = children; } - #value: T; + #value: T | UNINITIALIZED; readonly #initialized: Marker; - #children: ReadonlySet; + #children: ReadonlySet; #finalized: Timestamp; readonly #description: Description; constructor( - id: ReactiveId, - value: T, + value: T | UNINITIALIZED, initialized: { - [REACTIVE]: Omit & { + [REACTIVE]: Omit & { lastUpdated: Timestamp; }; }, - children: Set, + children: Set, finalized: Timestamp, description: Description ) { @@ -120,11 +120,11 @@ export class Frame this.#description = description; } - get [REACTIVE](): CompositeInternals { + get [REACTIVE](): FormulaCore { return { type: "composite", description: this.#description, - children: () => { + children: (): SubscriptionTarget[] => { return [this.#initialized, ...this.#children]; }, }; @@ -134,20 +134,24 @@ export class Frame return this.#description; } - #update( - this: Frame, - value: U, - children: Set, - finalized: Timestamp - ): Frame; - #update( - value: T, - children: Set, - finalized: Timestamp - ): Frame; + evaluate(block: () => T, stack: FrameStack): Frame { + const activeFrame = stack.start(this); + + try { + stack.willEvaluate(); + const result = block(); + const frame = stack.end(activeFrame, result); + stack.updateSubscriptions(frame); + return frame; + } catch (e) { + stack.finally(activeFrame); + throw e; + } + } + #update( value: T, - children: Set, + children: Set, finalized: Timestamp ): this { if (Object.is(this.#value, UNINITIALIZED)) { @@ -163,7 +167,7 @@ export class Frame validate(): FrameValidation> { if ( this.#value === UNINITIALIZED || - ReactiveProtocol.lastUpdatedIn([...this.#children]).gt(this.#finalized) + SubscriptionTarget.lastUpdatedIn([...this.#children]).gt(this.#finalized) ) { return { status: "invalid" }; } else { @@ -186,12 +190,12 @@ export class ActiveFrame { readonly #updating: Frame | null; readonly #prev: ActiveFrame | null; - readonly #children: Set; + readonly #children: Set; private constructor( updating: Frame | null, prev: ActiveFrame | null, - children: Set, + children: Set, readonly description: Description ) { this.#updating = updating; @@ -199,7 +203,7 @@ export class ActiveFrame { this.#children = children; } - add(child: ReactiveProtocol): void { + add(child: SubscriptionTarget): void { this.#children.add(child); } diff --git a/packages/universal/timeline/src/timeline/frames.ts b/packages/universal/timeline/src/timeline/frames.ts index 1249fdd6..e3fa5895 100644 --- a/packages/universal/timeline/src/timeline/frames.ts +++ b/packages/universal/timeline/src/timeline/frames.ts @@ -1,9 +1,10 @@ import type { DebugTimeline, Stack } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { type UNINITIALIZED, REACTIVE } from "@starbeam/shared"; +import type { CellCore } from "@starbeam/interfaces"; +import { REACTIVE } from "@starbeam/shared"; -import { type Frame, ActiveFrame } from "./frame.js"; -import { ReactiveProtocol } from "./protocol.js"; +import { ActiveFrame, type Frame } from "./frame.js"; +import { SubscriptionTarget } from "./protocol.js"; import type { Subscriptions } from "./subscriptions.js"; import type { Timeline } from "./timeline.js"; @@ -14,7 +15,7 @@ export class FrameStack { static didConsumeCell( frames: FrameStack, - reactive: ReactiveProtocol, + reactive: SubscriptionTarget, caller: Stack ): void { frames.#debug.consumeCell(reactive[REACTIVE], caller); @@ -24,7 +25,7 @@ export class FrameStack { static didConsumeFrame( frames: FrameStack, frame: interfaces.Frame, - diff: interfaces.Diff, + diff: interfaces.Diff, caller: Stack ): void { frames.#debug.consumeFrame(frame, diff, caller); @@ -53,49 +54,54 @@ export class FrameStack { return this.#timeline.log; } - create(options: { - evaluate: () => T; - description: interfaces.Description; - }): Frame; - // FIXME Overloads shouldn't trigger member-ordering + /** + * Evaluate a block of code, returning a new Frame. + */ + evaluate( + block: () => T, + { + description, + }: { + description: interfaces.Description; + } + ): Frame { + const frame = this.#start(description) as ActiveFrame; - create(options: { description: interfaces.Description }): ActiveFrame; - // FIXME Overloads shouldn't trigger member-ordering + try { + const result = block(); + return this.#end(frame, result); + } catch (e) { + this.finally(frame); + throw e; + } + } - create({ - evaluate, + /** + * Open a new frame, returning an `ActiveFrame`. + * + * Any consumptions between a call to `open()` and the call to + * {@linkcode ActiveFrame.prototype.finalize ActiveFrame#finalize} are assigned to this frame. + */ + open({ description, }: { - evaluate?: () => T; description: interfaces.Description; - }): Frame | ActiveFrame { - const frame = this.#start(description) as ActiveFrame; - - if (evaluate) { - try { - const result = evaluate(); - return this.#end(frame, result); - } catch (e) { - this.finally(frame); - throw e; - } - } else { - return frame; - } + }): ActiveFrame { + return this.#start(description) as ActiveFrame; } - #didConsumeReactive(reactive: ReactiveProtocol, caller: Stack): void { + #didConsumeReactive(reactive: SubscriptionTarget, caller: Stack): void { const frame = this.currentFrame; if (frame) { frame.add(reactive); return; } else { - const delegatesTo = ReactiveProtocol.subscribesTo(reactive).filter((r) => - ReactiveProtocol.is(r, "mutable") - ); + const delegatesTo = SubscriptionTarget.subscriptionTargets( + reactive + ).filter((r) => SubscriptionTarget.is(r, "mutable")); for (const target of delegatesTo) { - if (ReactiveProtocol.is(target, "mutable")) { + if (SubscriptionTarget.is(target, "mutable")) { this.#timeline.untrackedRead(target, caller); } } @@ -112,6 +118,26 @@ export class FrameStack { this.#current = prev; } + /** @internal */ + start(frame: Frame): ActiveFrame { + return this.#start(frame.description, frame) as ActiveFrame; + } + + /** @internal */ + willEvaluate(): void { + this.#timeline.willEvaluate(); + } + + /** @internal */ + end(frame: ActiveFrame, value: T): Frame { + return this.#end(frame, value); + } + + /** @internal */ + updateSubscriptions(frame: Frame): void { + this.#subscriptions.update(frame); + } + #start( description: interfaces.Description, frame?: Frame @@ -124,44 +150,7 @@ export class FrameStack { )); } - update(options: { - updating: Frame; - evaluate: () => T; - }): Frame; - // FIXME Overloads shouldn't trigger member-ordering - - update({ - updating, - }: { - updating: Frame; - }): ActiveFrame; - // FIXME Overloads shouldn't trigger member-ordering - - update({ - updating, - evaluate: callback, - }: { - updating: Frame; - evaluate?: () => T; - }): Frame | ActiveFrame { - const activeFrame = this.#start( - updating.description, - updating - ) as ActiveFrame; - - if (callback) { - try { - this.#timeline.willEvaluate(); - const result = callback(); - const frame = this.#end(activeFrame, result); - this.#subscriptions.update(frame); - return frame; - } catch (e) { - this.finally(activeFrame); - throw e; - } - } else { - return activeFrame; - } + update(frame: Frame): ActiveFrame { + return this.#start(frame.description, frame) as ActiveFrame; } } diff --git a/packages/universal/timeline/src/timeline/protocol.ts b/packages/universal/timeline/src/timeline/protocol.ts index 886be4f4..e9f4e536 100644 --- a/packages/universal/timeline/src/timeline/protocol.ts +++ b/packages/universal/timeline/src/timeline/protocol.ts @@ -1,56 +1,83 @@ import type * as Debug from "@starbeam/debug"; import { Desc, Tree } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; +import type { + CellCore, + DelegateCore, + FormulaCore, + StaticCore, +} from "@starbeam/interfaces"; import { REACTIVE } from "@starbeam/shared"; import { isPresent } from "@starbeam/verify"; import { Timestamp, zero } from "./timestamp.js"; +export type Reactive = interfaces.Reactive; + interface ExhaustiveMatcher { - mutable: (internals: interfaces.MutableInternals) => T; - composite: (internals: interfaces.CompositeInternals) => T; - delegate: (internals: interfaces.DelegateInternals) => T; - static: (internals: interfaces.StaticInternals) => T; + mutable: (internals: CellCore) => T; + composite: (internals: FormulaCore) => T; + delegate: (internals: DelegateCore) => T; + static: (internals: StaticCore) => T; } +export type ReactiveCore = interfaces.ReactiveCore; + interface DefaultMatcher extends Partial> { - default: (internals: interfaces.ReactiveInternals) => T; + default: (internals: ReactiveCore) => T; } type Matcher = ExhaustiveMatcher | DefaultMatcher; -export type ReactiveProtocol< - I extends interfaces.ReactiveInternals = interfaces.ReactiveInternals -> = interfaces.ReactiveProtocol; +export type SubscriptionTarget< + I extends interfaces.ReactiveCore = interfaces.ReactiveCore +> = interfaces.SubscriptionTarget; -export const ReactiveProtocol = { - description(this: void, reactive: ReactiveProtocol): Debug.Description { - return ReactiveInternals.description(reactive[REACTIVE]); +export const SubscriptionTarget = { + description(this: void, reactive: SubscriptionTarget): Debug.Description { + return ReactiveCore.description(reactive[REACTIVE]); }, - id(this: void, reactive: ReactiveProtocol): interfaces.ReactiveId { - return ReactiveInternals.id(reactive[REACTIVE]); + id(this: void, reactive: SubscriptionTarget): interfaces.ReactiveId { + return ReactiveCore.id(reactive[REACTIVE]); }, - is( + is( this: void, - reactive: ReactiveProtocol, + reactive: SubscriptionTarget, kind: T ): reactive is { - [REACTIVE]: Extract; + [REACTIVE]: Extract; } { - return ReactiveInternals.is(reactive[REACTIVE], kind); + return ReactiveCore.is(reactive[REACTIVE], kind); }, - match(this: void, reactive: ReactiveProtocol, matcher: Matcher): T { - return ReactiveInternals.match(reactive[REACTIVE], matcher); + match(this: void, reactive: SubscriptionTarget, matcher: Matcher): T { + return ReactiveCore.match(reactive[REACTIVE], matcher); }, - subscribesTo(this: void, reactive: ReactiveProtocol): ReactiveProtocol[] { + /** + * This method returns a list of reactives that subscribers to the original reactive should + * actually subscribe to. + * + * Normally, this is just the reactive itself. However, if a ReactiveProtocol is a delegate, + * subscribers can subscribe directly to the delegate's targets. + * + * This is because a delegate's targets can't change, so it's safe to subscribe directly to the + * targets. + * + * This makes it possible to create abstractions around reactive values that don't have to worry + * about manually updating their subscribers when their values change. + */ + subscriptionTargets( + this: void, + reactive: SubscriptionTarget + ): SubscriptionTarget[] { const internals = reactive[REACTIVE]; + console.log({ internals }); if (internals.type === "delegate") { - return internals.delegate.flatMap(ReactiveProtocol.subscribesTo); + return internals.targets.flatMap(SubscriptionTarget.subscriptionTargets); } else { return [reactive]; } @@ -58,28 +85,28 @@ export const ReactiveProtocol = { dependencies( this: void, - reactive: ReactiveProtocol - ): Iterable { - return ReactiveInternals.dependencies(reactive[REACTIVE]); + reactive: SubscriptionTarget + ): Iterable { + return ReactiveCore.dependencies(reactive[REACTIVE]); }, *dependenciesInList( this: void, - children: readonly ReactiveProtocol[] - ): Iterable { + children: readonly SubscriptionTarget[] + ): Iterable { for (const child of children) { - yield* ReactiveInternals.dependencies(child[REACTIVE]); + yield* ReactiveCore.dependencies(child[REACTIVE]); } }, - lastUpdated(this: void, reactive: ReactiveProtocol): Timestamp { - return ReactiveInternals.lastUpdated(reactive[REACTIVE]); + lastUpdated(this: void, reactive: SubscriptionTarget): Timestamp { + return ReactiveCore.lastUpdated(reactive[REACTIVE]); }, - lastUpdatedIn(this: void, reactives: ReactiveProtocol[]): Timestamp { + lastUpdatedIn(this: void, reactives: SubscriptionTarget[]): Timestamp { let lastUpdatedTimestamp = zero(); - for (const child of ReactiveProtocol.dependenciesInList(reactives)) { + for (const child of SubscriptionTarget.dependenciesInList(reactives)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } @@ -90,46 +117,49 @@ export const ReactiveProtocol = { log( this: void, - reactive: ReactiveProtocol, + reactive: SubscriptionTarget, options: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): void { - ReactiveInternals.log(reactive[REACTIVE], options); + ReactiveCore.log(reactive[REACTIVE], options); }, debug( this: void, - reactive: ReactiveProtocol, + reactive: SubscriptionTarget, { implementation = false, source = false, }: { implementation?: boolean; source?: boolean } = {} ): string { - return ReactiveInternals.debug(reactive[REACTIVE], { + return ReactiveCore.debug(reactive[REACTIVE], { implementation, source, }); }, } as const; -export const ReactiveInternals = { +export const ReactiveCore = { is( this: void, - internals: interfaces.ReactiveInternals, + internals: interfaces.ReactiveCore, kind: T - ): internals is Extract { + ): internals is Extract { return internals.type === kind; }, - id( - this: void, - internals: interfaces.ReactiveInternals - ): interfaces.ReactiveId { + id(this: void, internals: interfaces.ReactiveCore): interfaces.ReactiveId { return internals.description.id; }, + /** + * Return a flat list of the mutable reactives that this reactive depends on. + * + * This list is only valid until the next time anyone reads from the reactive. It's intended to be + * used along with code that updates the dependencies whenever the reactive is read. + */ *dependencies( - internals: interfaces.ReactiveInternals - ): Iterable { + internals: interfaces.ReactiveCore + ): Iterable { switch (internals.type) { case "static": return; @@ -141,52 +171,52 @@ export const ReactiveInternals = { yield internals; break; case "delegate": - for (const target of ReactiveInternals.subscribesTo(internals)) { - yield* ReactiveInternals.dependencies(target); + for (const target of ReactiveCore.subscribesTo(internals)) { + yield* ReactiveCore.dependencies(target); } break; case "composite": - yield* ReactiveProtocol.dependenciesInList(internals.children()); + yield* SubscriptionTarget.dependenciesInList(internals.children()); break; } }, *dependenciesInList( this: void, - children: readonly ReactiveInternals[] - ): Iterable { + children: readonly interfaces.ReactiveCore[] + ): Iterable { for (const child of children) { - yield* ReactiveInternals.dependencies(child); + yield* ReactiveCore.dependencies(child); } }, subscribesTo( this: void, - internals: interfaces.ReactiveInternals - ): interfaces.ReactiveInternals[] { + internals: interfaces.ReactiveCore + ): interfaces.ReactiveCore[] { if (internals.type === "delegate") { - return internals.delegate.flatMap((protocol) => - ReactiveProtocol.subscribesTo(protocol).map((p) => p[REACTIVE]) + return internals.targets.flatMap((protocol) => + SubscriptionTarget.subscriptionTargets(protocol).map((p) => p[REACTIVE]) ); } else { return [internals]; } }, - lastUpdated(this: void, internals: ReactiveInternals): Timestamp { + lastUpdated(this: void, internals: interfaces.ReactiveCore): Timestamp { switch (internals.type) { case "static": return zero(); case "mutable": return internals.lastUpdated; case "delegate": { - const delegates = ReactiveInternals.subscribesTo(internals); - return ReactiveInternals.lastUpdatedIn(delegates); + const delegates = ReactiveCore.subscribesTo(internals); + return ReactiveCore.lastUpdatedIn(delegates); } case "composite": { let lastUpdatedTimestamp = zero(); - for (const child of ReactiveInternals.dependencies(internals)) { + for (const child of ReactiveCore.dependencies(internals)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } @@ -197,10 +227,10 @@ export const ReactiveInternals = { } }, - lastUpdatedIn(this: void, internals: ReactiveInternals[]): Timestamp { + lastUpdatedIn(this: void, core: ReactiveCore[]): Timestamp { let lastUpdatedTimestamp = zero(); - for (const child of ReactiveInternals.dependenciesInList(internals)) { + for (const child of ReactiveCore.dependenciesInList(core)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } @@ -209,20 +239,20 @@ export const ReactiveInternals = { return lastUpdatedTimestamp; }, - description(this: void, internals: ReactiveInternals): Debug.Description { - return internals.description; + description(this: void, core: ReactiveCore): Debug.Description { + return core.description; }, debug( this: void, - internals: interfaces.ReactiveInternals, + internals: ReactiveCore, { implementation = false, source = false, id = false, }: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): string { - const dependencies = [...ReactiveInternals.dependencies(internals)]; + const dependencies = [...ReactiveCore.dependencies(internals)]; const descriptions = new Set( dependencies.map((dependency) => { return implementation @@ -243,22 +273,24 @@ export const ReactiveInternals = { log( this: void, - internals: interfaces.ReactiveInternals, + internals: interfaces.ReactiveCore, options: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): void { - const debug = ReactiveInternals.debug(internals, options); + const debug = ReactiveCore.debug(internals, options); console.group( - ReactiveInternals.description(internals).describe({ id: options.id }), - `(updated at ${ - Timestamp.debug(ReactiveInternals.lastUpdated(internals)).at - })` + ReactiveCore.description(internals).describe({ id: options.id }), + `(updated at ${Timestamp.debug(ReactiveCore.lastUpdated(internals)).at})` ); console.log(debug); console.groupEnd(); }, - match(this: void, internals: ReactiveInternals, matcher: Matcher): T { + match( + this: void, + internals: interfaces.ReactiveCore, + matcher: Matcher + ): T { const fn = matcher[internals.type]; if (typeof fn === "function") { return fn(internals as never); @@ -268,20 +300,36 @@ export const ReactiveInternals = { }, }; -export type ReactiveInternals = interfaces.ReactiveInternals; +function is( + this: void, + value: T | interfaces.Reactive +): value is interfaces.Reactive { + return !!( + value && + (typeof value === "object" || typeof value === "function") && + REACTIVE in value + ); +} -export type Reactive< - T, - I extends ReactiveInternals = ReactiveInternals -> = interfaces.Reactive; +// export const SubscriptionTarget = { +// is, + +// from( +// this: void, +// value: T | Reactive, +// description?: string | Debug.Description +// ): Reactive { +// if (is(value)) { +// return value; +// } else { +// return new Static(value, Desc("static", description)); +// } +// }, +// }; export const Reactive = { is(this: void, value: unknown): value is interfaces.Reactive { - return !!( - value && - (typeof value === "object" || typeof value === "function") && - REACTIVE in value - ); + return is(value) && hasRead(value); }, from( @@ -297,29 +345,13 @@ export const Reactive = { }, }; -export type ReactiveCore< - T, - I extends ReactiveInternals = ReactiveInternals -> = interfaces.ReactiveCore; - -export const ReactiveCore = { - is(value: unknown): value is interfaces.ReactiveCore { - return !!( - value && - (typeof value === "object" || typeof value === "function") && - REACTIVE in value && - hasRead(value) - ); - }, -}; - function hasRead(value: object): value is { read: () => T } { return "read" in value && typeof value.read === "function"; } -class Static { +class Static implements interfaces.ReactiveValue { readonly #value: T; - readonly [REACTIVE]: interfaces.StaticInternals; + readonly [REACTIVE]: interfaces.StaticCore; constructor(value: T, description: Debug.Description) { this.#value = value; diff --git a/packages/universal/timeline/src/timeline/subscriptions.md b/packages/universal/timeline/src/timeline/subscriptions.md new file mode 100644 index 00000000..19d0cfd1 --- /dev/null +++ b/packages/universal/timeline/src/timeline/subscriptions.md @@ -0,0 +1,84 @@ +In the public `TIMELINE` API, you can subscribe to changes to any reactive. + +Internally, Starbeam has a direct mapping from cells to notifications. + +Whenever a formula is recomputed, it gets a new set of cell dependencies. The formula's +subscriptions are removed from any cells that are no longer dependencies, and added to any +cells that became dependencies. + +```ts +const shouldDisplay = Cell(false); +const name = Cell("Tom"); + +const user = Formula(() => { + if (shouldDisplay.current) { + return name.current; + } else { + return ""; + } +}); + +user.current; // "" + +TIMELINE.on.change(user, () => console.log("user changed")); +``` + +At this point, the `user` formula has `shouldDisplay` as a dependency. This means that Starbeam has +a mapping from `shouldDisplay` to `() => console.log("user changed")` (the notification). + +If this happens: + +```ts +name.current = "Thomas"; +``` + +The notification will not fire, since there's no mapping from `name` to the notification. + +If this happens: + +```ts +shouldDisplay.current = true; +``` + +The notification _will_ fire, since there's a mapping from `shouldDisplay` to the notification. + +At this point, the `user` formula hasn't yet been recomputed, so the mapping hasn't changed either. + +That means that if you do this: + +```ts +user.current = "Tomas"; +``` + +The notification will _not_ fire again. + +In real-world scenarios, the notification will cause the formula to be recomputed at some later +point. After _that_ happens: + +```ts +someElement.textContent = user.current; // "Tomas" +``` + +At _this_ point, there's a mapping from _both_ `shouldDisplay` _and_ `name` to the notification. + +You may be surprised that we don't need another notification, simply because the formula wasn't +recomputed. + +--- + +The **TL;DR** is that notifications inform you that a reactive value has changed since the last time +it was computed (they are not a general-purpose pub-sub mechanism). + +--- + +The slightly longer version is: After the first notification, Starbeam has _already_ notified you +that the formula needs to be recomputed, and you scheduled some code to run later that will +recompute the formula and do something with the new value. + +At this point, you already know that you need to recompute the formula, but you haven't actually +computed the value yet. If more changes to reactive dependencies happen before you recompute the +value, nothing changes about that. + +When you finally _do_ recompute the value, you get a value that is guaranteed to be up to date. You +didn't need to recompute the value in between (and learn about the change to dependencies) to get +the right behavior. diff --git a/packages/universal/timeline/src/timeline/subscriptions.ts b/packages/universal/timeline/src/timeline/subscriptions.ts index 97230f11..92ded9af 100644 --- a/packages/universal/timeline/src/timeline/subscriptions.ts +++ b/packages/universal/timeline/src/timeline/subscriptions.ts @@ -1,170 +1,238 @@ -import type { MutableInternals, Timestamp } from "@starbeam/interfaces"; +import type { CellCore, Diff, FormulaCore } from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; -import { ReactiveProtocol } from "./protocol.js"; -import { getNow } from "./timestamp.js"; +import { SubscriptionTarget } from "./protocol.js"; import { diff } from "./utils.js"; -export class Subscription { - #dependencies: Set; - #lastNotified: undefined | Timestamp; - #ready: (internals: MutableInternals) => void; - - constructor( - dependencies: Set, - lastNotified: undefined | Timestamp, - ready: (internals: MutableInternals) => void - ) { - this.#dependencies = dependencies; - this.#lastNotified = lastNotified; - this.#ready = ready; +export type NotifyReady = (internals: CellCore) => void; + +/** + * A subscription is a weak mapping from individual cells to the subscriptions that depend on them. + * + * This is an interesting problem because consumers can subscribe to reactive values whose cell + * depenencies change over time (such as formulas). + * + * We want: + * + * 1. A direct mapping from cells to subscribers. This means that we know (directly) what + * subscribers are interested in a cell mutation, allowing us to do synchronous bookkeeping + * related to subscribers as mutations occur. + * 2. A weak mapping from cells to subscribers. If a cell is GC'ed, then no additional mutations to + * it can occur, and we don't need to maintain a hard reference to the cell or its subscribers. + * + * We accomplish this by keeping a weak mapping from formulas to subscriptions, and a second weak + * mapping from cells to subscriptions. + * + * When a cell is mutated, we have a direct mapping to the subscriber without additional + * computations. + * + * When a formula is recomputed, we: + * + * 1. get its subscriptions from the mapping. + * 2. remove the subscriptions from any cells that are no longer dependencies. + * 3. add the subscriptions to any cells that are now dependencies. + * + * This makes reading formulas a bit slower, but simplifies cell mutation. This is a good trade-off, + * since formula computation is typically scheduled, and happens in response to potentially many + * mutations. + * + * @see [A detailed description of the approach used here](./subscriptions.md) + */ +export class Subscriptions { + static create(): Subscriptions { + return new Subscriptions(); } - update(dependencies: Set): void { - this.#dependencies = dependencies; - } + readonly #formulaMap = FormulaMap.empty(); + readonly #cellMap = CellMap.empty(); + + /** + * Register a notification for a reactive value. + * + * - If the reactive value is a cell, the notification will fire whenever the cell is mutated. + * - If the reactive value is a formula, the notification will fire whenever any of the cell's + * dependencies of the formula are mutated. + * + * --- + * TODO: Is it necessary to fire notifications when the formula is recomputed? What if a formula + * has two consumers, and they both read the formula, get dependencies A and B and register + * notifications. The first consumer reads the formula again, producing dependencies B and C, and + * then mutates A. + * + * Current thinking: Since the notifications never fired, that must mean that neither A nor B + * changed. Therefore, re-computing the formula should not have invalidated, so the whole scenario + * is impossible. + * + * However, it probably *is* possible with `PolledFormula`, which intentionally allows a formula + * to be recomputed even if its Starbeam deps haven't changed. One possibility is that we might + * want to restrict `PolledFormula` to its current use-case of a single consumer. Alternatively, + * we may want to fire notifications whenever a `PolledFormula` is recomputed and produces + * different dependencies. + */ + register(target: SubscriptionTarget, ready: NotifyReady): Unsubscribe { + const subscriptionTargets = SubscriptionTarget.subscriptionTargets(target); + + const unsubscribes = subscriptionTargets.map((t) => { + const entry = this.#formulaMap.register(t); + for (const dependency of SubscriptionTarget.dependencies(t)) { + this.#cellMap.register(dependency, entry); + } - get dependencies(): Set { - return this.#dependencies; - } + return entry.subscribe(ready); + }); - get lastNotified(): Timestamp | undefined { - return this.#lastNotified; + return () => { + for (const unsubscribe of unsubscribes) { + unsubscribe(); + } + }; } - notify(timestamp: Timestamp, internals: MutableInternals): void { - this.#lastNotified = timestamp; - this.#ready(internals); + /** + * Notify the subscribers of a particular cell. This happens synchronously during mutation. + */ + notify(mutable: CellCore): void { + this.#cellMap.notify(mutable); } -} -export class Subscriptions { - static create(): Subscriptions { - return new Subscriptions(new WeakMap(), new WeakMap()); + /** + * Update the internal mappings for a formula. This happens after a formula was recomputed. It + * results in removing mappings from cells that are no longer dependencies and adding mappings for + * cells that have become dependencies. + */ + update(frame: SubscriptionTarget): void { + const cellMap = this.#cellMap; + + const { add, remove, entry } = this.#formulaMap.update(frame); + cellMap.remove(remove, entry); + cellMap.add(add, entry); } +} - #reactiveMap: WeakMap>; - #depMap: WeakMap>; - - private constructor( - pollableMap: WeakMap>, - readyMap: WeakMap> - ) { - this.#reactiveMap = pollableMap; - this.#depMap = readyMap; +/** + * A mapping from reactives (basically formulas) to their subscriptions. + */ +class FormulaMap { + static empty(): FormulaMap { + return new FormulaMap(); } - notify(dependency: MutableInternals): void { - const subscriptions = this.#depMap.get(dependency); - - if (subscriptions) { - for (const subscription of subscriptions) { - subscription.notify(getNow(), dependency); - } + readonly #mapping = new WeakMap(); + + update( + frame: SubscriptionTarget + ): Diff & { entry: ReactiveSubscription } { + const entry = this.#mapping.get(frame); + + if (entry) { + return { ...entry.update(frame), entry }; + } else { + const entry = ReactiveSubscription.create(frame); + this.#mapping.set(frame, entry); + return { + add: new Set(SubscriptionTarget.dependencies(frame)), + remove: new Set(), + entry, + }; } } - register( - reactive: ReactiveProtocol, - ready: (internals: MutableInternals) => void - ): Unsubscribe { - const subscribesTo = ReactiveProtocol.subscribesTo(reactive); - const dependencies = new Set(ReactiveProtocol.dependencies(reactive)); + register(target: SubscriptionTarget): ReactiveSubscription { + let entry = this.#mapping.get(target); - const subscription = new Subscription(dependencies, getNow(), ready); - - for (const dependency of dependencies) { - this.#addDep(dependency, subscription); - } - - for (const subscribeTo of subscribesTo) { - this.#addReactive(subscribeTo, subscription); + if (!entry) { + entry = ReactiveSubscription.create(target); + this.#mapping.set(target, entry); } - return () => { - for (const subscribeTo of subscribesTo) { - this.#removeReactive(subscribeTo, subscription); - } - }; + return entry; } +} - update(reactive: ReactiveProtocol): void { - const pollables = this.#reactiveMap.get(reactive); - - if (!pollables) { - return; - } +class ReactiveSubscription { + static create(target: SubscriptionTarget): ReactiveSubscription { + const deps = new Set(SubscriptionTarget.dependencies(target)); + return new ReactiveSubscription(deps); + } - const next = new Set(ReactiveProtocol.dependencies(reactive)); - const lastUpdatedNext = ReactiveProtocol.lastUpdated(reactive); + #deps: Set; + readonly #ready = new Set(); - for (const pollable of pollables) { - const prev = pollable.dependencies; - const lastNotified = pollable.lastNotified; + private constructor(deps: Set) { + this.#deps = deps; + } - const delta = diff(prev, next); - const { add, remove } = delta; + subscribe(ready: NotifyReady): Unsubscribe { + this.#ready.add(ready); + return () => this.#ready.delete(ready); + } - for (const dep of add) { - this.#addDep(dep, pollable); - } + notify(internals: CellCore): void { + for (const ready of this.#ready) { + ready(internals); + } + } - for (const dep of remove) { - this.#removeDep(dep, pollable); - } + update(frame: SubscriptionTarget): Diff { + const prev = this.#deps; + const next = new Set(SubscriptionTarget.dependencies(frame)); + this.#deps = next; - pollable.update(next); + return diff(prev, next); + } +} - if (lastNotified === undefined || lastUpdatedNext.gt(lastNotified)) { - // pollable.notify(Timestamp.now()); - } - } +/** + * CellMap keeps track of the current subscriptions for a specific cell. + * + * When a mutation occurs, the `CellMap` knows exactly which subscriptions it needs to notify, + * which keeps the mutation path simple. + */ +class CellMap { + static empty(): CellMap { + return new CellMap(); } - #addReactive(reactive: ReactiveProtocol, pollable: Subscription): void { - let pollableSet = this.#reactiveMap.get(reactive); + readonly #entriesMap = new WeakMap>(); - if (!pollableSet) { - pollableSet = new Set(); - this.#reactiveMap.set(reactive, pollableSet); + remove(mutables: ReadonlySet, entry: ReactiveSubscription): void { + for (const mutable of mutables) { + this.#entriesMap.get(mutable)?.delete(entry); } - - pollableSet.add(pollable); } - #removeReactive( - reactive: ReactiveProtocol, - subscription: Subscription - ): void { - const pollableSet = this.#reactiveMap.get(reactive); - - if (pollableSet) { - pollableSet.delete(subscription); + add(mutables: ReadonlySet, entry: ReactiveSubscription): void { + for (const mutable of mutables) { + this.#initialized(mutable).add(entry); } + } - const dependencies = subscription.dependencies; + register(mutable: CellCore, entry: ReactiveSubscription): void { + this.#initialized(mutable).add(entry); + } - for (const dependency of dependencies) { - this.#removeDep(dependency, subscription); + notify(mutable: CellCore): void { + for (const entry of this.#entries(mutable)) { + entry.notify(mutable); } } - #addDep(dependency: MutableInternals, subscription: Subscription): void { - let depSet = this.#depMap.get(dependency); + *#entries(mutable: CellCore): IterableIterator { + const entries = this.#entriesMap.get(mutable); - if (!depSet) { - depSet = new Set(); - this.#depMap.set(dependency, depSet); + if (entries) { + yield* entries; } - - depSet.add(subscription); } - #removeDep(dependency: MutableInternals, pollable: Subscription): void { - const readySet = this.#depMap.get(dependency); + #initialized(mutable: CellCore): Set { + let entries = this.#entriesMap.get(mutable); - if (readySet) { - readySet.delete(pollable); + if (!entries) { + entries = new Set(); + this.#entriesMap.set(mutable, entries); } + + return entries; } } diff --git a/packages/universal/timeline/src/timeline/timeline.ts b/packages/universal/timeline/src/timeline/timeline.ts index 9643dcf8..2503a233 100644 --- a/packages/universal/timeline/src/timeline/timeline.ts +++ b/packages/universal/timeline/src/timeline/timeline.ts @@ -1,18 +1,16 @@ import type { Stack } from "@starbeam/debug"; -import { - type DebugFilter, - type DebugListener, - DebugTimeline, -} from "@starbeam/debug"; +import { DebugTimeline } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; +import type { CellCore } from "@starbeam/interfaces"; -import { LIFETIME } from "../lifetime/api.js"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { FrameStack } from "./frames.js"; -import { ReactiveProtocol } from "./protocol.js"; -import { Subscriptions } from "./subscriptions.js"; +import { SubscriptionTarget } from "./protocol.js"; +import { type NotifyReady, Subscriptions } from "./subscriptions.js"; import { getNow, NOW } from "./timestamp.js"; +type TimelineOp = "consumed" | "bumped" | "evaluating" | "initial"; + /** * # How Subscriptions Work at the Lowest Level * @@ -30,7 +28,7 @@ import { getNow, NOW } from "./timestamp.js"; * * ## Delegates * - * If an object implementing {@linkcode ReactiveProtocol} simply polls another reactive object, it + * If an object implementing {@linkcode ReactiveCore} simply polls another reactive object, it * can use a {@linkcode DelegateInternals} property to point to that object. In this case, the * object doesn't need to worry about `TIMELINE.update`. * @@ -40,31 +38,12 @@ import { getNow, NOW } from "./timestamp.js"; * reactives that depend on that dependency. */ export class Timeline { - readonly #afterRender: Set<() => void>; - - declare attach: ( - notify: () => void, - options?: { filter: DebugFilter } - ) => DebugListener; - #debugTimeline: DebugTimeline | null = null; readonly #frame: FrameStack; - #lastOp: "consumed" | "bumped" | "evaluating" | "initial"; on = { - rendered: (callback: () => void): (() => void) => { - this.#afterRender.add(callback); - - return () => { - this.#afterRender.delete(callback); - }; - }, - - change: ( - input: ReactiveProtocol, - ready: (internals: interfaces.MutableInternals) => void - ): Unsubscribe => { - return this.#subscriptions.register(input, ready); + change: (target: SubscriptionTarget, ready: NotifyReady): Unsubscribe => { + return this.#subscriptions.register(target, ready); }, } as const; @@ -73,10 +52,11 @@ export class Timeline { * tracking frame, but which are used to produce rendered outputs. */ #readAssertions = new Set< - (reactive: ReactiveProtocol, caller: Stack) => void + (reactive: SubscriptionTarget, caller: Stack) => void >(); readonly #subscriptions: Subscriptions; + #lastOp: TimelineOp; /** * In debug mode, register a barrier for untracked reads. This allows you to throw an error if an @@ -84,39 +64,21 @@ export class Timeline { * produce rendered content. */ declare untrackedReadBarrier: ( - assertion: (reactive: ReactiveProtocol, caller: Stack) => void + assertion: (reactive: SubscriptionTarget, caller: Stack) => void ) => void; static create(): Timeline { - return new Timeline(Subscriptions.create(), new Set(), "initial"); + return new Timeline(Subscriptions.create(), "initial"); } - private constructor( - subscriptions: Subscriptions, - onAdvance: Set<() => void>, - lastOp: "consumed" | "bumped" | "evaluating" | "initial" - ) { + private constructor(subscriptions: Subscriptions, lastOp: TimelineOp) { this.#subscriptions = subscriptions; - this.#afterRender = onAdvance; this.#frame = FrameStack.empty(this, subscriptions); this.#lastOp = lastOp; if (import.meta.env.DEV) { - this.attach = ( - notify: () => void, - options: { filter: DebugFilter } = { filter: { type: "all" } } - ): DebugListener => { - const listener = this.#debug.attach(notify, options); - - LIFETIME.on.cleanup(listener, () => { - listener.detach(); - }); - - return listener; - }; - this.untrackedReadBarrier = ( - assertion: (reactive: ReactiveProtocol, caller: Stack) => void + assertion: (reactive: SubscriptionTarget, caller: Stack) => void ): void => { this.#readAssertions.add(assertion); }; @@ -125,13 +87,10 @@ export class Timeline { get #debug(): DebugTimeline { if (!this.#debugTimeline) { - const debugTimeline = (this.#debugTimeline = DebugTimeline.create( + this.#debugTimeline = DebugTimeline.create( { now: getNow }, - ReactiveProtocol - )); - this.on.rendered(() => { - debugTimeline.notify(); - }); + SubscriptionTarget + ); } return this.#debugTimeline; @@ -165,10 +124,7 @@ export class Timeline { } } - bump( - mutable: interfaces.MutableInternals, - caller: Stack - ): interfaces.Timestamp { + bump(mutable: interfaces.CellCore, caller: Stack): interfaces.Timestamp { const now = this.#adjustTimestamp("bumped"); if (import.meta.env.DEV) { @@ -179,17 +135,14 @@ export class Timeline { return now; } - didConsumeCell( - cell: ReactiveProtocol, - caller: Stack - ): void { + didConsumeCell(cell: SubscriptionTarget, caller: Stack): void { this.#adjustTimestamp("consumed"); FrameStack.didConsumeCell(this.#frame, cell, caller); } didConsumeFrame( frame: interfaces.Frame, - diff: interfaces.Diff, + diff: interfaces.Diff, caller: Stack ): void { this.#adjustTimestamp("consumed"); @@ -211,7 +164,9 @@ export class Timeline { * For example, Formulas call this method after recomputing their value, which results in a * possible change to their dependencies. */ - update(reactive: ReactiveProtocol): void { + update( + reactive: interfaces.SubscriptionTarget + ): void { this.#subscriptions.update(reactive); } @@ -230,7 +185,7 @@ export class Timeline { /// DEBUG MODE /// /** @internal */ - untrackedRead(cell: ReactiveProtocol, caller: Stack): void { + untrackedRead(cell: SubscriptionTarget, caller: Stack): void { for (const assertion of this.#readAssertions) { assertion(cell, caller); } diff --git a/packages/universal/timeline/tests/consume.spec.ts b/packages/universal/timeline/tests/consume.spec.ts index 027c31a3..743125dc 100644 --- a/packages/universal/timeline/tests/consume.spec.ts +++ b/packages/universal/timeline/tests/consume.spec.ts @@ -12,16 +12,18 @@ describe("consumption", () => { const id = getID(); const here = Stack.fromCaller(-1); - const frame = TIMELINE.frame.create({ - evaluate: () => { + const frame = TIMELINE.frame.evaluate( + () => { TIMELINE.didConsumeCell(instance, here); }, - description: descriptionFrom({ - id, - type: "formula", - api: "Formula", - }), - }); + { + description: descriptionFrom({ + id, + type: "formula", + api: "Formula", + }), + } + ); const stale = new Staleness(); TIMELINE.on.change(frame, () => { diff --git a/packages/universal/timeline/tests/pollable.spec.ts b/packages/universal/timeline/tests/pollable.spec.ts index 64a8b863..ad87d969 100644 --- a/packages/universal/timeline/tests/pollable.spec.ts +++ b/packages/universal/timeline/tests/pollable.spec.ts @@ -1,6 +1,6 @@ import { isPresentArray } from "@starbeam/core-utils"; import { descriptionFrom } from "@starbeam/debug"; -import type { ReactiveCore } from "@starbeam/interfaces"; +import type { ReactiveValue } from "@starbeam/interfaces"; import { Frame, REACTIVE, TIMELINE } from "@starbeam/timeline"; import { describe, expect, test } from "vitest"; @@ -42,12 +42,9 @@ describe("pollable", () => { // The subscription fires because we updated a dependency of an already-read reactive. expect(stale).toBe(true); - TIMELINE.update(sum); - expect(stale).toBe(true); expect(sum.read()).toBe(3); stale = false; - TIMELINE.update(sum); expect(stale).toBe(false); const current = satisfying(numbers.current, isPresentArray); @@ -63,7 +60,7 @@ describe("pollable", () => { test("subscribing to a delegate", () => { const cell = Cell(0); - const delegate: ReactiveCore = { + const delegate: ReactiveValue = { read: () => cell.current, [REACTIVE]: { type: "delegate", @@ -71,7 +68,7 @@ describe("pollable", () => { type: "delegate", api: "delegate", }), - delegate: [cell], + targets: [cell], }, }; @@ -94,7 +91,7 @@ describe("pollable", () => { test("subscribing to a delegate with a composite", () => { const { sum, numbers } = Sum(); - const delegate: ReactiveCore = { + const delegate: ReactiveValue = { read: () => sum.read(), [REACTIVE]: { type: "delegate", @@ -102,7 +99,7 @@ describe("pollable", () => { type: "delegate", api: "delegate", }), - delegate: [sum], + targets: [sum], }, }; @@ -130,12 +127,10 @@ describe("pollable", () => { unsubscribe(); satisfying(numbers.current, isPresentArray)[0].current++; - TIMELINE.update(sum); expect(stale).toBe(false); expect(delegate.read()).toBe(5); numbers.current = [...numbers.current, Cell(3)]; - TIMELINE.update(sum); expect(stale).toBe(false); expect(delegate.read()).toBe(8); @@ -143,7 +138,7 @@ describe("pollable", () => { }); function Sum(): { - sum: ReactiveCore; + sum: ReactiveValue; numbers: Cell[]>; } { const numbers: Cell[]> = Cell([]); @@ -156,14 +151,13 @@ function Sum(): { }) ); - const sum: ReactiveCore = { + const sum: ReactiveValue = { read: () => { return Frame.value( - TIMELINE.frame.update({ - updating: frame, - evaluate: () => - numbers.current.reduce((acc, cell) => acc + cell.current, 0), - }) + frame.evaluate( + () => numbers.current.reduce((acc, cell) => acc + cell.current, 0), + TIMELINE.frame + ) ); }, [REACTIVE]: { @@ -172,7 +166,7 @@ function Sum(): { type: "delegate", api: "delegate", }), - delegate: [frame], + targets: [frame], }, }; diff --git a/packages/universal/timeline/tests/protocol.spec.ts b/packages/universal/timeline/tests/protocol.spec.ts index 62f1cc30..694c9b08 100644 --- a/packages/universal/timeline/tests/protocol.spec.ts +++ b/packages/universal/timeline/tests/protocol.spec.ts @@ -1,11 +1,16 @@ import { callerStack, descriptionFrom } from "@starbeam/debug"; -import type { CompositeInternals } from "@starbeam/interfaces"; -import { REACTIVE, ReactiveProtocol, TIMELINE, zero } from "@starbeam/timeline"; +import type { FormulaCore } from "@starbeam/interfaces"; +import { + REACTIVE, + SubscriptionTarget, + TIMELINE, + zero, +} from "@starbeam/timeline"; import { beforeAll, describe, expect, it } from "vitest"; import { Cell, FreezableCell, Static } from "./support/mini-reactives.js"; -describe("ReactiveProtocol", () => { +describe("SubscriptionTarget", () => { beforeAll(() => { // make sure the timeline is not at 0, which would make a comparison with TIMELINE.now sometimes // equivalent to Timestamp.zero(), and we want to test the difference. @@ -25,8 +30,8 @@ describe("ReactiveProtocol", () => { it("has the zero timestamp for lastUpdated", () => { const tom = Static("Tom Dale"); - expect(String(ReactiveProtocol.lastUpdated(tom))).toBe(String(zero())); - expect(String(ReactiveProtocol.lastUpdatedIn([tom]))).toBe( + expect(String(SubscriptionTarget.lastUpdated(tom))).toBe(String(zero())); + expect(String(SubscriptionTarget.lastUpdatedIn([tom]))).toBe( String(zero()) ); }); @@ -34,8 +39,8 @@ describe("ReactiveProtocol", () => { it("has no dependencies", () => { const tom = Static("Tom Dale"); - expect([...ReactiveProtocol.dependencies(tom)]).toEqual([]); - expect([...ReactiveProtocol.dependenciesInList([tom])]).toEqual([]); + expect([...SubscriptionTarget.dependencies(tom)]).toEqual([]); + expect([...SubscriptionTarget.dependenciesInList([tom])]).toEqual([]); }); }); @@ -43,16 +48,16 @@ describe("ReactiveProtocol", () => { it("has the current timestamp for lastUpdated", () => { const original = TIMELINE.now; const tom = Cell("Tom"); - expect(String(ReactiveProtocol.lastUpdated(tom))).toBe( + expect(String(SubscriptionTarget.lastUpdated(tom))).toBe( String(TIMELINE.now) ); const nullvox = Cell("nullvox"); const nullvoxTimestamp = TIMELINE.now; - expect(String(ReactiveProtocol.lastUpdated(nullvox))).toBe( + expect(String(SubscriptionTarget.lastUpdated(nullvox))).toBe( String(nullvoxTimestamp) ); - expect(String(ReactiveProtocol.lastUpdatedIn([tom, nullvox]))).toBe( + expect(String(SubscriptionTarget.lastUpdatedIn([tom, nullvox]))).toBe( String(TIMELINE.now) ); @@ -60,13 +65,13 @@ describe("ReactiveProtocol", () => { tom.current = "Tom Dale"; expect(String(TIMELINE.now)).not.toBe(String(original)); - expect(String(ReactiveProtocol.lastUpdated(tom))).toBe( + expect(String(SubscriptionTarget.lastUpdated(tom))).toBe( String(TIMELINE.now) ); - expect(String(ReactiveProtocol.lastUpdated(nullvox))).toBe( + expect(String(SubscriptionTarget.lastUpdated(nullvox))).toBe( String(nullvoxTimestamp) ); - expect(String(ReactiveProtocol.lastUpdatedIn([tom, nullvox]))).toBe( + expect(String(SubscriptionTarget.lastUpdatedIn([tom, nullvox]))).toBe( String(TIMELINE.now) ); }); @@ -75,11 +80,12 @@ describe("ReactiveProtocol", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - expect([...ReactiveProtocol.dependencies(tom)]).toEqual([tom[REACTIVE]]); - expect([...ReactiveProtocol.dependenciesInList([tom, nullvox])]).toEqual([ + expect([...SubscriptionTarget.dependencies(tom)]).toEqual([ tom[REACTIVE], - nullvox[REACTIVE], ]); + expect([ + ...SubscriptionTarget.dependenciesInList([tom, nullvox]), + ]).toEqual([tom[REACTIVE], nullvox[REACTIVE]]); }); it("has no dependencies if it's frozen", () => { @@ -89,10 +95,10 @@ describe("ReactiveProtocol", () => { nullvox.current = "@nullvoxpopuli"; - expect([...ReactiveProtocol.dependencies(tom)]).toEqual([]); - expect([...ReactiveProtocol.dependenciesInList([tom, nullvox])]).toEqual([ - nullvox[REACTIVE], - ]); + expect([...SubscriptionTarget.dependencies(tom)]).toEqual([]); + expect([ + ...SubscriptionTarget.dependenciesInList([tom, nullvox]), + ]).toEqual([nullvox[REACTIVE]]); }); }); @@ -101,7 +107,7 @@ describe("ReactiveProtocol", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - const composite: CompositeInternals = { + const composite: FormulaCore = { type: "composite", description: descriptionFrom({ type: "formula", @@ -112,22 +118,22 @@ describe("ReactiveProtocol", () => { }, }; - const Both: ReactiveProtocol = { + const Both: SubscriptionTarget = { [REACTIVE]: composite, }; - expect(String(ReactiveProtocol.lastUpdated(Both))).toBe( + expect(String(SubscriptionTarget.lastUpdated(Both))).toBe( String(TIMELINE.now) ); - expect([...ReactiveProtocol.dependencies(Both)]).toEqual([ + expect([...SubscriptionTarget.dependencies(Both)]).toEqual([ tom[REACTIVE], nullvox[REACTIVE], ]); tom.current = "Tom Dale"; - expect(String(ReactiveProtocol.lastUpdated(Both))).toBe( + expect(String(SubscriptionTarget.lastUpdated(Both))).toBe( String(TIMELINE.now) ); }); diff --git a/packages/universal/timeline/tests/subscription.ts b/packages/universal/timeline/tests/subscription.ts index ae926e11..0e7f00d1 100644 --- a/packages/universal/timeline/tests/subscription.ts +++ b/packages/universal/timeline/tests/subscription.ts @@ -1,4 +1,4 @@ -import { descriptionFrom } from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; import { Frame, TIMELINE } from "@starbeam/timeline"; import { describe, expect, test } from "vitest"; @@ -8,21 +8,17 @@ describe("frames", () => { test("subscription before first consumption", () => { const cell = Cell("Tom Dale"); - const formula = TIMELINE.frame.create({ - evaluate: () => cell.current, - description: descriptionFrom({ - type: "formula", - api: "Formula", - }), + const frame = TIMELINE.frame.evaluate(() => cell.current, { + description: Desc("formula"), }); let stale = false; - const unsubscribe = TIMELINE.on.change(formula, () => { + const unsubscribe = TIMELINE.on.change(frame, () => { stale = true; }); - expect(Frame.value(formula)).toBe("Tom Dale"); + expect(Frame.value(frame)).toBe("Tom Dale"); // The pollable doesn't fire initially. expect(stale).toBe(false); @@ -32,38 +28,34 @@ describe("frames", () => { expect(stale).toBe(true); stale = false; - TIMELINE.frame.update({ updating: formula, evaluate: () => cell.current }); + frame.evaluate(() => cell.current, TIMELINE.frame); - expect(Frame.value(formula)).toBe("Jerry Seinfeld"); + expect(Frame.value(frame)).toBe("Jerry Seinfeld"); unsubscribe(); cell.current = "J. Seinfeld"; expect(stale).toBe(false); - TIMELINE.frame.update({ updating: formula, evaluate: () => cell.current }); + frame.evaluate(() => cell.current, TIMELINE.frame); expect(stale).toBe(false); // The lack of a subscription doesn't make the value incorrect - expect(Frame.value(formula)).toBe("J. Seinfeld"); + expect(Frame.value(frame)).toBe("J. Seinfeld"); }); test("subscription after first consumption", () => { const cell = Cell("Tom Dale"); - const formula = TIMELINE.frame.create({ - evaluate: () => cell.current, - description: descriptionFrom({ - type: "formula", - api: "Formula", - }), + const frame = TIMELINE.frame.evaluate(() => cell.current, { + description: Desc("formula"), }); let stale = false; - expect(Frame.value(formula)).toBe("Tom Dale"); + expect(Frame.value(frame)).toBe("Tom Dale"); - const unsubscribe = TIMELINE.on.change(formula, () => { + const unsubscribe = TIMELINE.on.change(frame, () => { stale = true; }); @@ -75,19 +67,18 @@ describe("frames", () => { expect(stale).toBe(true); stale = false; - TIMELINE.frame.update({ updating: formula, evaluate: () => cell.current }); - - expect(Frame.value(formula)).toBe("Jerry Seinfeld"); + frame.evaluate(() => cell.current, TIMELINE.frame); + expect(Frame.value(frame)).toBe("Jerry Seinfeld"); unsubscribe(); cell.current = "J. Seinfeld"; expect(stale).toBe(false); - TIMELINE.frame.update({ updating: formula, evaluate: () => cell.current }); + frame.evaluate(() => cell.current, TIMELINE.frame); expect(stale).toBe(false); // The lack of a subscription doesn't make the value incorrect - expect(Frame.value(formula)).toBe("J. Seinfeld"); + expect(Frame.value(frame)).toBe("J. Seinfeld"); }); }); diff --git a/packages/universal/timeline/tests/support/mini-reactives.ts b/packages/universal/timeline/tests/support/mini-reactives.ts index b9714434..b6db5ccf 100644 --- a/packages/universal/timeline/tests/support/mini-reactives.ts +++ b/packages/universal/timeline/tests/support/mini-reactives.ts @@ -1,92 +1,103 @@ -import { type Stack, callerStack, descriptionFrom } from "@starbeam/debug"; -import type { MutableInternals, ReactiveCore } from "@starbeam/interfaces"; -import type { UNINITIALIZED } from "@starbeam/shared"; import { - type ReactiveProtocol, - type Timestamp, - diff, - Frame, - REACTIVE, - TIMELINE, - zero, -} from "@starbeam/timeline"; - -export interface Cell extends ReactiveProtocol { - current: T; - read: (stack: Stack) => T; -} - -export interface FreezableCell extends Cell { + callerStack, + Desc, + descriptionFrom, + type Stack, +} from "@starbeam/debug"; +import type { + CellCore, + ReactiveCell, + ReactiveValue, +} from "@starbeam/interfaces"; +import { REACTIVE, type UNINITIALIZED } from "@starbeam/shared"; +import { type SubscriptionTarget } from "@starbeam/timeline"; +import { diff, Frame, TIMELINE, type Timestamp } from "@starbeam/timeline"; + +export interface FreezableCell extends ReactiveCell { freeze: () => void; } -export function Cell(value: T): Cell { - let lastUpdated = TIMELINE.next(); - const internals: MutableInternals = { - type: "mutable", - description: descriptionFrom({ - api: "Cell", - type: "cell", - }), - get lastUpdated(): Timestamp { - return lastUpdated; - }, - }; +export type Cell = ReactiveCell; + +class CellImpl implements ReactiveCell { + readonly [REACTIVE]: CellCore; + #value: T; + #lastUpdated: Timestamp; + constructor(value: T, timestamp: Timestamp) { + const lastUpdated = (): Timestamp => this.#lastUpdated; + + this[REACTIVE] = { + type: "mutable", + description: Desc("cell"), + get lastUpdated(): Timestamp { + return lastUpdated(); + }, + }; + this.#value = value; + this.#lastUpdated = timestamp; + } - return { - [REACTIVE]: internals, - read(caller: Stack) { - TIMELINE.didConsumeCell(this, caller); - return value; - }, - get current() { - return this.read(callerStack()); - }, - set current(newValue: T) { - value = newValue; + read(caller: Stack): T { + TIMELINE.didConsumeCell(this, caller); + return this.#value; + } + get current(): T { + return this.read(callerStack()); + } + set current(newValue: T) { + this.#value = newValue; - lastUpdated = TIMELINE.bump(internals, callerStack()); - }, - }; + this.#lastUpdated = TIMELINE.bump(this[REACTIVE], callerStack()); + } } -export function FreezableCell(value: T): FreezableCell { - let lastUpdated = zero(); - let isFrozen = false; +export function Cell(value: T): CellImpl { + return new CellImpl(value, TIMELINE.next()); +} - const internals: MutableInternals = { - type: "mutable", - description: descriptionFrom({ - api: "FreezableCell", - type: "cell", - }), - get lastUpdated(): Timestamp { - return lastUpdated; - }, - isFrozen: () => isFrozen, - }; +class FreezableCellImpl implements ReactiveCell { + readonly [REACTIVE]: CellCore; + #isFrozen = false; + #value: T; + #lastUpdated: Timestamp; + constructor(value: T, timestamp: Timestamp) { + const lastUpdated = (): Timestamp => this.#lastUpdated; + + this[REACTIVE] = { + type: "mutable", + description: Desc("cell"), + get lastUpdated(): Timestamp { + return lastUpdated(); + }, + isFrozen: () => this.#isFrozen, + }; + this.#value = value; + this.#lastUpdated = timestamp; + } - return { - [REACTIVE]: internals, - read(caller: Stack) { - TIMELINE.didConsumeCell(this, caller); - return value; - }, - get current() { - return this.read(callerStack()); - }, - set current(newValue: T) { - value = newValue; + read(caller: Stack): T { + TIMELINE.didConsumeCell(this, caller); + return this.#value; + } + get current(): T { + return this.read(callerStack()); + } + set current(newValue: T) { + this.#value = newValue; - lastUpdated = TIMELINE.bump(internals, callerStack()); - }, - freeze() { - isFrozen = true; - }, - }; + this.#lastUpdated = TIMELINE.bump(this[REACTIVE], callerStack()); + } + + freeze(): void { + this.#isFrozen = true; + } +} + +export function FreezableCell(value: T): FreezableCellImpl { + return new FreezableCellImpl(value, TIMELINE.next()); } -export function Static(value: T): ReactiveCore { +export function Static(value: T): ReactiveValue { return { [REACTIVE]: { type: "static", @@ -125,12 +136,7 @@ export function Formula(computation: () => T): { return validation.value; } - const result = Frame.value( - TIMELINE.frame.update({ - updating: frame, - evaluate: computation, - }) - ); + const result = Frame.value(frame.evaluate(computation, TIMELINE.frame)); TIMELINE.update(frame); TIMELINE.didConsumeFrame(frame, diff.empty(), caller); return result; @@ -140,11 +146,11 @@ export function Formula(computation: () => T): { } export function Marker(): { - instance: ReactiveProtocol; + instance: SubscriptionTarget; update: () => void; } { let lastUpdated = TIMELINE.next(); - const internals: MutableInternals = { + const internals: CellCore = { type: "mutable", description: descriptionFrom({ type: "cell", diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index a0c95555..da2b43d5 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -1,5 +1,5 @@ export { DEBUG_RENDERER } from "./src/debug-renderer.js"; -export { type Equality, Cell } from "./src/reactive-core/cell.js"; +export { Cell, type Equality } from "./src/reactive-core/cell.js"; export { Custom, CustomBlueprint, @@ -22,9 +22,9 @@ export { ResourceList, } from "./src/reactive-core/higher-level/resource-list.js"; export { + Factory, type IntoReactiveObject, type IntoResource, - Factory, } from "./src/reactive-core/into.js"; export { Marker } from "./src/reactive-core/marker.js"; export type { @@ -35,24 +35,24 @@ export type { } from "./src/reactive-core/reactive.js"; export { Reactive } from "./src/reactive-core/reactive.js"; export { + Resource, type ResourceBlueprint, type ResourceFactory, type ResourceReturn, - Resource, } from "./src/reactive-core/resource/resource.js"; export type { ResourceRun } from "./src/reactive-core/resource/run.js"; export { - type ServiceBlueprint, createService, reactiveService, Service, service, + type ServiceBlueprint, } from "./src/reactive-core/service.js"; export { Static } from "./src/reactive-core/static.js"; export { type Variant, type VariantEntry, - type VariantType, Variants, + type VariantType, } from "./src/reactive-core/variants.js"; export { LIFETIME, REACTIVE, TIMELINE } from "@starbeam/timeline"; diff --git a/packages/universal/universal/src/reactive-core/cell.ts b/packages/universal/universal/src/reactive-core/cell.ts index ed502c01..be701450 100644 --- a/packages/universal/universal/src/reactive-core/cell.ts +++ b/packages/universal/universal/src/reactive-core/cell.ts @@ -1,14 +1,15 @@ import { isObject } from "@starbeam/core-utils"; import { - type Description, - type Stack, callerStack, + type Description, descriptionFrom, DisplayStruct, + type Stack, } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; +import type { ReactiveValue } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import { type Reactive, INSPECT, REACTIVE, TIMELINE } from "@starbeam/timeline"; +import { INSPECT, REACTIVE, TIMELINE } from "@starbeam/timeline"; import type { MutableInternalsImpl } from "../storage.js"; import { MutableInternals } from "../storage.js"; @@ -20,9 +21,7 @@ export interface CellPolicy { export type Equality = (a: T, b: T) => boolean; -export class ReactiveCell - implements Reactive -{ +export class ReactiveCell implements ReactiveValue { static create( value: T, internals: MutableInternalsImpl, diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/universal/src/reactive-core/delegate.ts index 02b55011..05a89177 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/universal/src/reactive-core/delegate.ts @@ -1,35 +1,35 @@ -import { type Description, callerStack, Desc } from "@starbeam/debug"; +import { callerStack, Desc, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { REACTIVE, ReactiveProtocol } from "@starbeam/timeline"; +import { REACTIVE, SubscriptionTarget } from "@starbeam/timeline"; -export class DelegateInternalsImpl implements interfaces.DelegateInternals { +export class DelegateInternalsImpl implements interfaces.DelegateCore { readonly type = "delegate"; constructor( readonly id: interfaces.ReactiveId, - readonly delegate: readonly interfaces.ReactiveProtocol[], + readonly targets: readonly interfaces.SubscriptionTarget[], readonly description: Description ) {} } export function DelegateInternals( - to: interfaces.ReactiveProtocol[] | interfaces.ReactiveProtocol, + to: interfaces.SubscriptionTarget[] | interfaces.SubscriptionTarget, options?: { description: string | Description } -): interfaces.DelegateInternals { +): interfaces.DelegateCore { const desc = Desc( "delegate", options?.description ?? - (Array.isArray(to) ? undefined : ReactiveProtocol.description(to)) + (Array.isArray(to) ? undefined : SubscriptionTarget.description(to)) ); return { type: "delegate", description: desc, - delegate: Array.isArray(to) ? to : [to], + targets: Array.isArray(to) ? to : [to], }; } -export function Wrap( +export function Wrap( reactive: U, value: T, desc?: Description | string @@ -59,15 +59,15 @@ export function Wrap( } function delegateDesc( - to: interfaces.ReactiveProtocol | interfaces.ReactiveProtocol[], + to: interfaces.SubscriptionTarget | interfaces.SubscriptionTarget[], desc?: string | Description ): Description { if (Array.isArray(to)) { return desc as Description; } else if (typeof desc === "string") { - return ReactiveProtocol.description(to).detail(desc); + return SubscriptionTarget.description(to).detail(desc); } else if (desc === undefined) { - return ReactiveProtocol.description(to).detail("{delegate}"); + return SubscriptionTarget.description(to).detail("{delegate}"); } else { return desc; } diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts index 3dc102a1..ecb2817b 100644 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/formula.ts @@ -1,11 +1,11 @@ import { - type Description, callerStack, + type Description, descriptionFrom, } from "@starbeam/debug"; import type { Reactive, Stack } from "@starbeam/interfaces"; import type { UNINITIALIZED } from "@starbeam/shared"; -import { ReactiveProtocol } from "@starbeam/timeline"; +import { SubscriptionTarget } from "@starbeam/timeline"; import { diff, Frame, REACTIVE, TIMELINE } from "@starbeam/timeline"; export interface FormulaValidation { @@ -26,27 +26,21 @@ export function FormulaValidation( fromUser: description, }); - const frame = Frame.uninitialized(TIMELINE.now, desc); + const frame = Frame.uninitialized(TIMELINE.now, desc); const update = (caller: Stack): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(ReactiveProtocol.dependencies(frame)); + const oldDeps = new Set(SubscriptionTarget.dependencies(frame)); - TIMELINE.frame.update({ - updating: frame, - evaluate: callback, - }); + frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(ReactiveProtocol.dependencies(frame)); + const newDeps = new Set(SubscriptionTarget.dependencies(frame)); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { - TIMELINE.frame.update({ - updating: frame, - evaluate: callback, - }); + frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); TIMELINE.didConsumeFrame(frame, diff.empty(), caller); } @@ -57,12 +51,12 @@ export function FormulaValidation( if (validation.status === "valid") { TIMELINE.didConsumeFrame(frame, diff.empty(), caller); - return frame as Frame; + return frame; } else { update(caller); } - return frame as Frame; + return frame; } return { poll, frame }; @@ -110,7 +104,7 @@ export function Formula( value: { type: "delegate", description: desc, - delegate: [formula.frame], + targets: [formula.frame], }, }); diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts index c815d9fe..2ad85bb3 100644 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts @@ -1,6 +1,6 @@ import { - type Description, callerStack, + type Description, descriptionFrom, } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; @@ -9,7 +9,7 @@ import { diff, Frame, REACTIVE, - ReactiveProtocol, + SubscriptionTarget, TIMELINE, } from "@starbeam/timeline"; @@ -48,22 +48,16 @@ export function PolledFormulaValidation( const update = (caller: Stack = callerStack()): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(ReactiveProtocol.dependencies(frame)); + const oldDeps = new Set(SubscriptionTarget.dependencies(frame)); - TIMELINE.frame.update({ - updating: frame, - evaluate: callback, - }); + frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(ReactiveProtocol.dependencies(frame)); + const newDeps = new Set(SubscriptionTarget.dependencies(frame)); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { - TIMELINE.frame.update({ - updating: frame, - evaluate: callback, - }); + frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); TIMELINE.didConsumeFrame(frame, diff.empty(), caller); } @@ -116,7 +110,7 @@ export function PolledFormula( value: { type: "delegate", description, - delegate: [formula.frame], + targets: [formula.frame], }, }); diff --git a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts index 8c10ea30..742dbd79 100644 --- a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts +++ b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts @@ -1,4 +1,4 @@ -import type { Reactive, ReactiveCore } from "@starbeam/interfaces"; +import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; import { Formula } from "../formula/formula.js"; import type { @@ -18,10 +18,10 @@ export function ResourceList>( map: (item: T) => R; } ): ResourceBlueprint[]> { - const prev = new Map(); + const prev = new Map(); return Resource(({ use }) => { - const result: ReactiveCore[] = []; + const result: ReactiveValue[] = []; for (const item of list) { const k = key(item); const r = prev.get(k); @@ -48,7 +48,7 @@ export function FormulaList( map: (item: T) => U; } ): Reactive { - const prev = new Map>(); + const prev = new Map>(); return Formula(() => { const result: U[] = []; diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts index 74d70399..2bb63814 100644 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ b/packages/universal/universal/src/reactive-core/marker.ts @@ -1,14 +1,18 @@ import { - type Description, callerStack, + type Description, descriptionFrom, } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; -import { type ReactiveProtocol, REACTIVE, TIMELINE } from "@starbeam/timeline"; +import { + REACTIVE, + type SubscriptionTarget, + TIMELINE, +} from "@starbeam/timeline"; -import { type MutableInternalsImpl, MutableInternals } from "../storage.js"; +import { MutableInternals, type MutableInternalsImpl } from "../storage.js"; -export class ReactiveMarker implements ReactiveProtocol { +export class ReactiveMarker implements SubscriptionTarget { static create(internals: MutableInternalsImpl): ReactiveMarker { return new ReactiveMarker(internals); } diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index f38f1ab2..582c797c 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -1,5 +1,5 @@ -import { type Description, Desc } from "@starbeam/debug"; -import type { ReactiveInternals } from "@starbeam/interfaces"; +import { Desc, type Description } from "@starbeam/debug"; +import type { ReactiveCore, ReactiveValue } from "@starbeam/interfaces"; import { Reactive as TimelineReactive } from "@starbeam/timeline"; import { isObject } from "@starbeam/verify"; @@ -34,8 +34,8 @@ export type IntoReactive = Reactive | T; export type TypedReactive< T, - I extends ReactiveInternals = ReactiveInternals -> = TimelineReactive; + I extends ReactiveCore = ReactiveCore +> = ReactiveValue; export type Reactive = TimelineReactive; diff --git a/packages/universal/universal/src/reactive-core/resource/resource.ts b/packages/universal/universal/src/reactive-core/resource/resource.ts index 96f85777..865323c4 100644 --- a/packages/universal/universal/src/reactive-core/resource/resource.ts +++ b/packages/universal/universal/src/reactive-core/resource/resource.ts @@ -13,9 +13,9 @@ * worrying about its lifetime. */ -import { type Description, Desc } from "@starbeam/debug"; +import { Desc, type Description } from "@starbeam/debug"; import { UNINITIALIZED } from "@starbeam/shared"; -import type { Reactive, ReactiveCore } from "@starbeam/timeline"; +import type { Reactive } from "@starbeam/timeline"; import { LIFETIME } from "@starbeam/timeline"; import { isWeakKey } from "@starbeam/verify"; @@ -167,7 +167,7 @@ export class ResourceBlueprint { export type ResourceReturn = | ResourceBlueprint - | ReactiveCore + | Reactive | T; type ResourceReturnType> = @@ -175,13 +175,13 @@ type ResourceReturnType> = export type AssimilatedResourceReturn> = Ret extends ResourceBlueprint - ? Resource & ReactiveCore> + ? Resource & Reactive> : Ret extends Reactive - ? Reactive & ReactiveCore> - : Ret extends ReactiveCore - ? ReactiveCore> + ? Reactive & Reactive> + : Ret extends Reactive + ? Reactive> : Ret extends ResourceReturn - ? Reactive & ReactiveCore + ? Reactive & Reactive : never; declare const RESOURCE: unique symbol; @@ -192,14 +192,12 @@ export function isResource(value: ResourceReturn): value is Resource { return !!(isWeakKey(value) && RESOURCES.get(value)?.hasLifetime); } -export function brandResource(reactive: ReactiveCore): Resource { +export function brandResource(reactive: Reactive): Resource { RESOURCES.set(reactive, { hasLifetime: true }); return reactive as unknown as Resource; } -export function brandReactiveResource( - reactive: ReactiveCore -): Resource { +export function brandReactiveResource(reactive: Reactive): Resource { RESOURCES.set(reactive, { hasLifetime: false }); return reactive as unknown as Resource; } diff --git a/packages/universal/universal/src/reactive-core/resource/run.ts b/packages/universal/universal/src/reactive-core/resource/run.ts index 839c2b4f..c84ce80c 100644 --- a/packages/universal/universal/src/reactive-core/resource/run.ts +++ b/packages/universal/universal/src/reactive-core/resource/run.ts @@ -1,5 +1,5 @@ import { type Description, Desc } from "@starbeam/debug"; -import type { Reactive, ReactiveCore } from "@starbeam/interfaces"; +import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; import { type Unsubscribe, LIFETIME } from "@starbeam/timeline"; import type { Handler, Resource, ResourceBlueprint } from "./resource"; @@ -42,7 +42,7 @@ export class ResourceRun { } readonly use = ( - resource: ResourceBlueprint | ReactiveCore | Resource | T, + resource: ResourceBlueprint | ReactiveValue | Resource | T, options?: { description?: string | Description | undefined } ): Reactive => { return this.#state.assimilateResourceReturn({ diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts index a32f9385..28f89402 100644 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ b/packages/universal/universal/src/reactive-core/resource/state.ts @@ -1,18 +1,17 @@ import type { Description } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import { LIFETIME, ReactiveCore } from "@starbeam/timeline"; +import { LIFETIME, Reactive } from "@starbeam/timeline"; import { Formula } from "../formula/formula.js"; import { Static } from "../static.js"; import { type AssimilatedResourceReturn, - type Resource, - type ResourceFactory, - type ResourceReturn, brandResource, isResource, + type Resource, ResourceBlueprint, + type ResourceFactory, + type ResourceReturn, } from "./resource"; import { ResourceRun } from "./run"; @@ -60,8 +59,8 @@ export class ResourceState { readonly #constructorFn: (resource: ResourceRun) => ResourceReturn; readonly #owner: object; #currentRun: ResourceRun | undefined = undefined; - readonly reactiveConstructor: Reactive>; - readonly reactiveInstance: Reactive>; + readonly reactiveConstructor: Reactive>; + readonly reactiveInstance: Reactive>; readonly resource: Resource; constructor( @@ -79,7 +78,7 @@ export class ResourceState { desc.detail("constructor") ); - let instance: ReactiveCore | undefined = undefined; + let instance: Reactive | undefined = undefined; let finalized = false; LIFETIME.on.cleanup(owner, () => { @@ -109,7 +108,7 @@ export class ResourceState { * that were used in the previous constructor and are used in the new constructor will be adopted * by the new constructor and not finalized. */ - next(): ReactiveCore { + next(): Reactive { return this.#startNextRun((nextRun) => { // Run the constructor function with the *new run*. We haven't yet finalized the previous run, // so the constructor function has an opportunity to use any resources that were used in the @@ -128,13 +127,11 @@ export class ResourceState { resource: returnValue, nextRun, desc: this.#desc, - }) as ReactiveCore; + }) as Reactive; }); } - #startNextRun( - callback: (run: ResourceRun) => ReactiveCore - ): ReactiveCore { + #startNextRun(callback: (run: ResourceRun) => Reactive): Reactive { const prevRun = this.#currentRun; const nextRun = new ResourceRun( @@ -167,7 +164,7 @@ export class ResourceState { if (isResource(resource)) { LIFETIME.link(nextRun, resource, { root: this.#owner }); return resource as AssimilatedResourceReturn; - } else if (ReactiveCore.is(resource)) { + } else if (Reactive.is(resource)) { return resource as AssimilatedResourceReturn; } else if (resource instanceof ResourceBlueprint) { return resource.use(nextRun, this) as AssimilatedResourceReturn; diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index 829eacdb..a51058b4 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -1,17 +1,14 @@ import type { Stack } from "@starbeam/debug"; import { - type Description, callerStack, + type Description, descriptionFrom, DisplayStruct, } from "@starbeam/debug"; +import type { FormulaCore } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import { - type ReactiveInternals, - type ReactiveProtocol, - REACTIVE, - TIMELINE, -} from "@starbeam/timeline"; +import type { SubscriptionTarget } from "@starbeam/timeline"; +import { REACTIVE, TIMELINE } from "@starbeam/timeline"; import { CompositeInternals } from "../storage.js"; import { Cell } from "./cell.js"; @@ -120,7 +117,7 @@ export class VariantGroup { } } -export class Variant implements ReactiveProtocol { +export class Variant implements SubscriptionTarget { static selected( type: string, typeMarker: Marker, @@ -212,7 +209,7 @@ export class Variant implements ReactiveProtocol { value: T | UNINITIALIZED; }; readonly #value: Cell; - readonly [REACTIVE]: ReactiveInternals; + readonly [REACTIVE]: FormulaCore; private constructor( type: string, @@ -220,7 +217,7 @@ export class Variant implements ReactiveProtocol { localTypeMarker: Marker, value: Cell, debug: { value: T | UNINITIALIZED }, - reactive: ReactiveInternals + reactive: FormulaCore ) { this.#type = type; this.#sharedTypeMarker = sharedTypeMarker; @@ -292,7 +289,7 @@ export interface ReadonlyVariants { } export interface Variants - extends ReactiveProtocol { + extends SubscriptionTarget { current: { [K in keyof Narrow]: K extends string ? Narrow[K] extends [] @@ -326,7 +323,7 @@ export interface Variants | undefined); } -class VariantsImpl implements ReactiveProtocol { +class VariantsImpl implements SubscriptionTarget { static create( value: InternalVariant, description: Description @@ -364,7 +361,7 @@ class VariantsImpl implements ReactiveProtocol { this.#current = current; } - get [REACTIVE](): ReactiveInternals { + get [REACTIVE](): FormulaCore { return CompositeInternals([this.#current], this.#description); } diff --git a/packages/universal/universal/src/storage.ts b/packages/universal/universal/src/storage.ts index e9a76389..e8efdab4 100644 --- a/packages/universal/universal/src/storage.ts +++ b/packages/universal/universal/src/storage.ts @@ -1,14 +1,11 @@ import type { Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { - type ReactiveProtocol, - type Timestamp, - TIMELINE, -} from "@starbeam/timeline"; +import type { SubscriptionTarget } from "@starbeam/timeline"; +import { TIMELINE, type Timestamp } from "@starbeam/timeline"; export function StaticInternals( description: Description -): interfaces.StaticInternals { +): interfaces.StaticCore { return { type: "static", description, @@ -17,9 +14,9 @@ export function StaticInternals( export function CompositeInternals( this: void, - children: ReactiveProtocol[], + children: SubscriptionTarget[], description: Description -): interfaces.CompositeInternals { +): interfaces.FormulaCore { return { type: "composite", description, @@ -31,17 +28,17 @@ export function CompositeInternals( export function DelegateInternals( this: void, - delegate: readonly ReactiveProtocol[], + delegate: readonly SubscriptionTarget[], description: Description -): interfaces.DelegateInternals { +): interfaces.DelegateCore { return { type: "delegate", description, - delegate: [...delegate], + targets: [...delegate], }; } -export class MutableInternalsImpl implements interfaces.MutableInternals { +export class MutableInternalsImpl implements interfaces.CellCore { #frozen = false; #lastUpdated: Timestamp = TIMELINE.now; readonly type = "mutable"; @@ -76,4 +73,4 @@ export function MutableInternals( return new MutableInternalsImpl(description); } -export type MutableInternals = interfaces.MutableInternals; +export type MutableInternals = interfaces.CellCore; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index 0d2bccf3..997d510e 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,5 +1,5 @@ import { entryPointFn } from "@starbeam/debug"; -import { Frame, ReactiveProtocol } from "@starbeam/timeline"; +import { Frame, SubscriptionTarget } from "@starbeam/timeline"; import { Cell, FormulaValidation, Reactive, Static } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; @@ -36,7 +36,7 @@ describe("reactive Factory", () => { const counter = Counter.create(); if (!import.meta.env.PROD) { - expect(ReactiveProtocol.description(counter).describe()).toBe( + expect(SubscriptionTarget.description(counter).describe()).toBe( "Counter 0" ); } diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts index 224f501b..1cd6574c 100644 --- a/packages/universal/universal/tests/setup.spec.ts +++ b/packages/universal/universal/tests/setup.spec.ts @@ -1,4 +1,4 @@ -import { ReactiveProtocol, TIMELINE } from "@starbeam/timeline"; +import { SubscriptionTarget, TIMELINE } from "@starbeam/timeline"; import { Cell, Setup } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -129,11 +129,11 @@ describe("Setup", () => { cleanupCounter: 0, }); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); setup(); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -143,11 +143,11 @@ describe("Setup", () => { // cellB is not used in the initial setup, so it doesn't invalidate the setup cellB.set(20); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); setup(); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -157,8 +157,8 @@ describe("Setup", () => { cellA.set(1); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = ReactiveProtocol.lastUpdated(setup); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(gt(ts)); + ts = SubscriptionTarget.lastUpdated(setup); expect(variable).toEqual({ cell: 0, @@ -168,7 +168,7 @@ describe("Setup", () => { setup(); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 20, @@ -178,8 +178,8 @@ describe("Setup", () => { cellA.set(2); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = ReactiveProtocol.lastUpdated(setup); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(gt(ts)); + ts = SubscriptionTarget.lastUpdated(setup); expect(variable).toEqual({ cell: 20, @@ -189,7 +189,7 @@ describe("Setup", () => { setup(); - expect(ReactiveProtocol.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 2, diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 796b252b..f6741815 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,4 +1,4 @@ -import { ReactiveProtocol } from "@starbeam/timeline"; +import { SubscriptionTarget } from "@starbeam/timeline"; import { Formula, TIMELINE, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -195,13 +195,15 @@ describe("Variants", () => { // eslint-disable-next-line @typescript-eslint/no-inferrable-types const debug: boolean = false; -function Stability(reactive: ReactiveProtocol): { readonly changed: boolean } { +function Stability(reactive: SubscriptionTarget): { + readonly changed: boolean; +} { let changed = false; TIMELINE.on.change(reactive, (internals) => { if (debug) { console.group( - ReactiveProtocol.description(reactive).describe(), + SubscriptionTarget.description(reactive).describe(), "invalidated by" ); console.log(internals.description.describe()); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91235adf..8d437b1d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,104 +3,98 @@ lockfileVersion: 5.4 overrides: '@rollup/plugin-commonjs': ^24.0.0 '@rollup/plugin-node-resolve': ^15.0.1 - '@types/eslint': ^8.4.10 - '@types/node': 18.11.18 - '@typescript-eslint/eslint-plugin': ^5.48.0 - '@typescript-eslint/parser': ^5.48.0 - '@vitest/ui': ^0.26.3 - eslint: ^8.31.0 + '@types/eslint': ^8.21.3 + '@types/node': 18.15.5 + '@typescript-eslint/eslint-plugin': ^5.56.0 + '@typescript-eslint/parser': ^5.56.0 + eslint: ^8.36.0 preact: ^10.11.3 rollup: ^3.9.1 - typescript: ^4.9.4 - vite: 4.0.4 + typescript: ^5.0.2 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 vue: ^3.2.39 importers: .: specifiers: - '@babel/eslint-parser': ^7.19.1 - '@babel/plugin-proposal-decorators': ^7.20.7 + '@babel/eslint-parser': ^7.21.3 + '@babel/plugin-proposal-decorators': ^7.21.0 '@babel/plugin-syntax-dynamic-import': ^7.8.3 - '@babel/plugin-transform-runtime': ^7.19.6 + '@babel/plugin-transform-runtime': ^7.21.0 '@babel/preset-env': ^7.20.2 '@babel/preset-react': ^7.18.6 - '@babel/preset-typescript': ^7.18.6 - '@babel/runtime': ^7.20.7 + '@babel/preset-typescript': ^7.21.0 + '@babel/runtime': ^7.21.0 '@changesets/changelog-git': ^0.1.14 - '@changesets/cli': ^2.26.0 + '@changesets/cli': ^2.26.1 '@changesets/config': ^2.3.0 '@starbeam-dev/build-support': workspace:1.0.0 '@starbeam/core-utils': workspace:^0.8.9 '@starbeam/eslint-plugin': workspace:^1.0.0 - '@types/eslint': ^8.4.10 - '@types/node': 18.11.18 - '@typescript-eslint/eslint-plugin': ^5.48.0 - '@typescript-eslint/parser': ^5.48.0 - '@vitest/ui': ^0.26.3 - eslint: ^8.31.0 + '@types/eslint': ^8.21.3 + '@types/node': 18.15.5 + '@typescript-eslint/eslint-plugin': ^5.56.0 + '@typescript-eslint/parser': ^5.56.0 + '@vitest/ui': ^0.29.7 + eslint: ^8.36.0 eslint-config-airbnb: ^19.0.4 - eslint-config-prettier: ^8.6.0 - eslint-import-resolver-typescript: ^3.5.2 - eslint-plugin-import: ^2.26.0 - eslint-plugin-jsonc: ^2.5.0 + eslint-config-prettier: ^8.8.0 + eslint-import-resolver-typescript: ^3.5.3 + eslint-plugin-import: ^2.27.5 + eslint-plugin-jsonc: ^2.7.0 eslint-plugin-prettier: ^4.2.1 - eslint-plugin-simple-import-sort: ^8.0.0 + eslint-plugin-simple-import-sort: ^10.0.0 eslint-plugin-unused-imports: ^2.0.0 esno: ^0.16.3 fast-glob: ^3.2.12 - happy-dom: ^8.1.1 - jsdom: ^20.0.3 - lint-to-the-future: ^1.3.1 - lint-to-the-future-eslint: ^1.0.1 - prettier: ^2.8.1 - tslib: ^2.4.1 - typescript: ^4.9.4 - vite: 4.0.4 - vitest: 0.26.3 + happy-dom: ^8.9.0 + jsdom: ^21.1.1 + prettier: ^2.8.6 + tslib: ^2.5.0 + typescript: ^5.0.2 + vite: 4.2.1 + vitest: 0.29.7 dependencies: '@starbeam/core-utils': link:packages/universal/core-utils devDependencies: - '@babel/eslint-parser': 7.19.1_cbdx2nt4qlpatq6svgwvehmsk4 - '@babel/plugin-proposal-decorators': 7.20.7_@babel+core@7.20.7 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-transform-runtime': 7.19.6_@babel+core@7.20.7 - '@babel/preset-env': 7.20.2_@babel+core@7.20.7 - '@babel/preset-react': 7.18.6_@babel+core@7.20.7 - '@babel/preset-typescript': 7.18.6_@babel+core@7.20.7 - '@babel/runtime': 7.20.7 + '@babel/eslint-parser': 7.21.3_pxuto7xgangxlusvzceggvrmde + '@babel/plugin-proposal-decorators': 7.21.0_@babel+core@7.21.3 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-transform-runtime': 7.21.0_@babel+core@7.21.3 + '@babel/preset-env': 7.20.2_@babel+core@7.21.3 + '@babel/preset-react': 7.18.6_@babel+core@7.21.3 + '@babel/preset-typescript': 7.21.0_@babel+core@7.21.3 + '@babel/runtime': 7.21.0 '@changesets/changelog-git': 0.1.14 - '@changesets/cli': 2.26.0 + '@changesets/cli': 2.26.1 '@changesets/config': 2.3.0 '@starbeam-dev/build-support': link:workspace/build '@starbeam/eslint-plugin': link:workspace/eslint - '@types/eslint': 8.4.10 - '@types/node': 18.11.18 - '@typescript-eslint/eslint-plugin': 5.48.0_k73wpmdolxikpyqun3p36akaaq - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe - '@vitest/ui': 0.26.3 - eslint: 8.31.0 - eslint-config-airbnb: 19.0.4_kdrd7zxcgo7evu26hvr6zfy33i - eslint-config-prettier: 8.6.0_eslint@8.31.0 - eslint-import-resolver-typescript: 3.5.2_ol7jqilc3wemtdbq3nzhywgxq4 - eslint-plugin-import: 2.26.0_cxu27kyieece4tnvunezm4whiq - eslint-plugin-jsonc: 2.5.0_eslint@8.31.0 - eslint-plugin-prettier: 4.2.1_32m5uc2milwdw3tnkcq5del26y - eslint-plugin-simple-import-sort: 8.0.0_eslint@8.31.0 - eslint-plugin-unused-imports: 2.0.0_zgazubnvp3urkgs5b7mw2pde3m + '@types/eslint': 8.21.3 + '@types/node': 18.15.5 + '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@vitest/ui': 0.29.7 + eslint: 8.36.0 + eslint-config-airbnb: 19.0.4_guhfqc3yvckhutqwrddiy54d5i + eslint-config-prettier: 8.8.0_eslint@8.36.0 + eslint-import-resolver-typescript: 3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy + eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq + eslint-plugin-jsonc: 2.7.0_eslint@8.36.0 + eslint-plugin-prettier: 4.2.1_ose2zoovovx4ulolhifz3tfzx4 + eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0 + eslint-plugin-unused-imports: 2.0.0_pjgbsoxltfjhart6hcjsvw66hu esno: 0.16.3 fast-glob: 3.2.12 - happy-dom: 8.1.1 - jsdom: 20.0.3 - lint-to-the-future: 1.3.1 - lint-to-the-future-eslint: 1.0.1_eslint@8.31.0 - prettier: 2.8.1 - tslib: 2.4.1 - typescript: 4.9.4 - vite: 4.0.4_@types+node@18.11.18 - vitest: 0.26.3_giuftcgfn5z4uy6bdlohvyimia + happy-dom: 8.9.0 + jsdom: 21.1.1 + prettier: 2.8.6 + tslib: 2.5.0 + typescript: 5.0.2 + vite: 4.2.1_@types+node@18.15.5 + vitest: 0.29.7_bi73zdcwqjrbwiah6tn5sspwie '@types/@rollup/plugin-commonjs': specifiers: @@ -114,6 +108,12 @@ importers: dependencies: '@rollup/plugin-node-resolve': 15.0.1 + '@types/ansicolor': + specifiers: + '@types/node': 18.15.5 + devDependencies: + '@types/node': 18.15.5 + '@types/rollup-plugin-polyfill-node': specifiers: rollup: ^3.9.1 @@ -122,15 +122,15 @@ importers: '@types/shell-escape-tag': specifiers: - '@types/node': 18.11.18 + '@types/node': 18.15.5 devDependencies: - '@types/node': 18.11.18 + '@types/node': 18.15.5 '@types/shell-split': specifiers: - '@types/node': 18.11.18 + '@types/node': 18.15.5 devDependencies: - '@types/node': 18.11.18 + '@types/node': 18.15.5 demos/preact: specifiers: @@ -138,12 +138,12 @@ importers: '@starbeam/js': workspace:^ '@starbeam/preact': workspace:^ '@starbeam/universal': workspace:^ - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' preact: ^10.11.3 purecss: ^3.0.0 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/js': link:../../packages/universal/js '@starbeam/preact': link:../../packages/preact/preact @@ -151,11 +151,11 @@ importers: preact: 10.11.3 purecss: 3.0.0 devDependencies: - '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.16.13 - '@vitest/ui': 0.26.3 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.17.12 + '@vitest/ui': 0.29.7 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 demos/preact-hello-world: specifiers: @@ -164,12 +164,12 @@ importers: '@starbeam/preact': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' preact: ^10.11.3 purecss: 3.0.0 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/js': link:../../packages/universal/js '@starbeam/preact': link:../../packages/preact/preact @@ -178,11 +178,11 @@ importers: preact: 10.11.3 purecss: 3.0.0 devDependencies: - '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.16.13 - '@vitest/ui': 0.26.3 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.17.12 + '@vitest/ui': 0.29.7 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 demos/react: specifiers: @@ -191,13 +191,13 @@ importers: '@starbeam/universal': workspace:^ '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' purecss: 3.0.0 react: ^18.1.0 react-dom: ^18.1.0 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/js': link:../../packages/universal/js '@starbeam/react': link:../../packages/react/react @@ -208,10 +208,10 @@ importers: devDependencies: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 - '@vitest/ui': 0.26.3 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + '@vitest/ui': 0.29.7 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 demos/react-jsnation: specifiers: @@ -224,7 +224,7 @@ importers: purecss: 3.0.0 react: ^18.1.0 react-dom: ^18.1.0 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 dependencies: '@starbeam/debug': link:../../packages/universal/debug @@ -237,8 +237,8 @@ importers: devDependencies: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 demos/react-jsnation/tests: specifiers: @@ -271,13 +271,13 @@ importers: '@starbeamx/devtool': workspace:^ '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' axios: ^1.2.2 react: ^18.1.0 react-dom: ^18.1.0 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/debug': link:../../packages/universal/debug '@starbeam/js': link:../../packages/universal/js @@ -291,10 +291,10 @@ importers: devDependencies: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 - '@vitest/ui': 0.26.3 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + '@vitest/ui': 0.29.7 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 demos/react-query: specifiers: @@ -306,15 +306,15 @@ importers: '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 '@types/styled-components': ^5.1.25 - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' axios: ^1.2.2 purecss: 3.0.0 react: ^18 react-dom: ^18 styled-components: ^5.3.5 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/js': link:../../packages/universal/js '@starbeam/react': link:../../packages/react/react @@ -328,12 +328,12 @@ importers: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 '@types/styled-components': 5.1.26 - '@vitest/ui': 0.26.3 + '@vitest/ui': 0.29.7 axios: 1.2.2 styled-components: 5.3.6_pumtretovylab5lwhztzjp2kuy - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 demos/react-stock-ticker: specifiers: @@ -344,13 +344,13 @@ importers: '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 '@types/react-portal': ^4.0.4 - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' react: ^18.1.0 react-dom: ^18.1.0 react-portal: ^4.2.2 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/js': link:../../packages/universal/js '@starbeam/react': link:../../packages/react/react @@ -363,10 +363,10 @@ importers: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 '@types/react-portal': 4.0.4 - '@vitest/ui': 0.26.3 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + '@vitest/ui': 0.29.7 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 demos/react-store: specifiers: @@ -377,13 +377,13 @@ importers: '@starbeamx/store': workspace:^ '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 - '@vitest/ui': ^0.26.3 + '@vitest/ui': '*' purecss: 3.0.0 react: ^18.1.0 react-dom: ^18.1.0 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 - vitest: 0.26.3 + vitest: '*' dependencies: '@starbeam/debug': link:../../packages/universal/debug '@starbeam/react': link:../../packages/react/react @@ -396,10 +396,10 @@ importers: devDependencies: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 - '@vitest/ui': 0.26.3 - vite: 4.0.4 - vite-plugin-fonts: 0.7.0_vite@4.0.4 - vitest: 0.26.3_@vitest+ui@0.26.3 + '@vitest/ui': 0.29.7 + vite: 4.2.1 + vite-plugin-fonts: 0.7.0_vite@4.2.1 + vitest: 0.29.7_@vitest+ui@0.29.7 packages/preact/preact: specifiers: @@ -553,7 +553,8 @@ importers: '@starbeam/universal': workspace:^ '@starbeam/use-strict-lifecycle': workspace:^ '@starbeam/verify': workspace:^ - '@types/react': ^18.0.26 + '@types/node': 18.15.5 + '@types/react': ^18.0.28 react: '*' react-dom: '*' dependencies: @@ -572,7 +573,8 @@ importers: devDependencies: '@domtree/flavors': link:../../../workspace/@domtree/flavors '@starbeam-dev/build-support': link:../../../workspace/build - '@types/react': 18.0.26 + '@types/node': 18.15.5 + '@types/react': 18.0.28 packages/react/react/tests: specifiers: @@ -582,8 +584,9 @@ importers: '@starbeam/react': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ - jsdom: ^20.0.3 - react: ^18 + jsdom: ^21.1.1 + react: ^18.2.0 + vitest: '*' dependencies: '@starbeam-workspace/react-test-utils': link:../../test-utils '@starbeam-workspace/test-utils': link:../../../universal/test-utils @@ -591,22 +594,25 @@ importers: '@starbeam/react': link:.. '@starbeam/timeline': link:../../../universal/timeline '@starbeam/universal': link:../../../universal/universal - jsdom: 20.0.3 + jsdom: 21.1.1 react: 18.2.0 + vitest: 0.29.7_jsdom@21.1.1 packages/react/test-utils: specifiers: '@starbeam-dev/build-support': workspace:* '@starbeam-workspace/test-utils': workspace:^ + '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/verify': workspace:^ - '@testing-library/react': latest + '@testing-library/react': ^14.0.0 '@types/react': ^18.0.26 react: '*' react-dom: '*' dependencies: '@starbeam-workspace/test-utils': link:../../universal/test-utils + '@starbeam/core-utils': link:../../universal/core-utils '@starbeam/debug': link:../../universal/debug '@starbeam/shared': link:../../universal/shared '@starbeam/verify': link:../../universal/verify @@ -614,7 +620,7 @@ importers: react-dom: 18.2.0_react@18.2.0 devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build - '@testing-library/react': 13.4.0_biqbaboplfbrettd7655fr4n2y + '@testing-library/react': 14.0.0_biqbaboplfbrettd7655fr4n2y '@types/react': 18.0.26 packages/react/use-strict-lifecycle: @@ -676,7 +682,8 @@ importers: '@starbeam/interfaces': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/verify': workspace:^ - '@types/node': 18.11.18 + '@types/ansicolor': workspace:^ + '@types/node': 18.15.5 ansicolor: ^1.1.100 buffer: ^6.0.3 stacktracey: ^2.1.8 @@ -691,7 +698,8 @@ importers: stacktracey: 2.1.8 devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build - '@types/node': 18.11.18 + '@types/ansicolor': link:../../../@types/ansicolor + '@types/node': 18.15.5 packages/universal/debug/tests: specifiers: @@ -881,14 +889,14 @@ importers: chrome-types: ^0.1.159 dirfilename: ^1.0.4 preact: ^10.11.3 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-mpa: ^1.1.3 devDependencies: - '@crxjs/vite-plugin': 2.0.0-beta.12 + '@crxjs/vite-plugin': 2.0.0-beta.15 chrome-types: 0.1.159 dirfilename: 1.1.1 preact: 10.11.3 - vite: 4.0.4 + vite: 4.2.1 vite-plugin-mpa: 1.1.4 packages/x/store: @@ -991,17 +999,17 @@ importers: '@eslint/eslintrc': ^1.4.1 '@rollup/plugin-commonjs': ^24.0.0 '@rollup/plugin-node-resolve': ^15.0.1 - '@types/node': 18.11.18 + '@types/node': 18.15.5 '@types/rollup-plugin-polyfill-node': workspace:* '@types/rollup__plugin-commonjs': workspace:^ '@types/rollup__plugin-node-resolve': workspace:^ - '@typescript-eslint/parser': ^5.48.0 - eslint: ^8.31.0 - eslint-config-prettier: ^8.6.0 - eslint-plugin-import: ^2.26.0 + '@typescript-eslint/parser': ^5.56.0 + eslint: ^8.36.0 + eslint-config-prettier: ^8.8.0 + eslint-plugin-import: ^2.27.5 eslint-plugin-json: ^3.1.0 eslint-plugin-prettier: ^4.2.1 - eslint-plugin-simple-import-sort: ^8.0.0 + eslint-plugin-simple-import-sort: ^10.0.0 eslint-plugin-unused-imports: ^2.0.0 magic-string: ^0.27.0 postcss: ^8.4.20 @@ -1009,73 +1017,73 @@ importers: rollup-plugin-polyfill-node: ^0.11.0 rollup-plugin-postcss: ^4.0.2 rollup-plugin-ts: '*' - typescript: ^4.9.4 - vite: 4.0.4 + typescript: ^5.0.2 + vite: 4.2.1 vite-plugin-fonts: 0.7.0 dependencies: - '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.16.13 + '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.17.12 '@eslint/eslintrc': 1.4.1 '@rollup/plugin-commonjs': 24.0.0_rollup@3.9.1 '@rollup/plugin-node-resolve': 15.0.1_rollup@3.9.1 '@types/rollup-plugin-polyfill-node': link:../../@types/rollup-plugin-polyfill-node '@types/rollup__plugin-commonjs': link:../../@types/@rollup/plugin-commonjs '@types/rollup__plugin-node-resolve': link:../../@types/@rollup/plugin-node-resolve - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe - eslint: 8.31.0 - eslint-config-prettier: 8.6.0_eslint@8.31.0 - eslint-plugin-import: 2.26.0_m2kn7xiag5lymyarkgri27ztxm + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + eslint: 8.36.0 + eslint-config-prettier: 8.8.0_eslint@8.36.0 + eslint-plugin-import: 2.27.5_cnkxirszkzb4o6ts7gbclno24e eslint-plugin-json: 3.1.0 - eslint-plugin-prettier: 4.2.1_32m5uc2milwdw3tnkcq5del26y - eslint-plugin-simple-import-sort: 8.0.0_eslint@8.31.0 - eslint-plugin-unused-imports: 2.0.0_eslint@8.31.0 + eslint-plugin-prettier: 4.2.1_ose2zoovovx4ulolhifz3tfzx4 + eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0 + eslint-plugin-unused-imports: 2.0.0_eslint@8.36.0 magic-string: 0.27.0 postcss: 8.4.20 rollup: 3.9.1 rollup-plugin-polyfill-node: 0.11.0_rollup@3.9.1 rollup-plugin-postcss: 4.0.2_postcss@8.4.20 - rollup-plugin-ts: 3.0.2_esmavzhadgk2idmxtiodxm33ma - vite: 4.0.4_@types+node@18.11.18 - vite-plugin-fonts: 0.7.0_vite@4.0.4 + rollup-plugin-ts: 3.0.2_tumybvdr6br7dr3yffpdihdhou + vite: 4.2.1_@types+node@18.15.5 + vite-plugin-fonts: 0.7.0_vite@4.2.1 devDependencies: - '@types/node': 18.11.18 - typescript: 4.9.4 + '@types/node': 18.15.5 + typescript: 5.0.2 workspace/eslint: specifiers: - '@types/eslint': ^8.4.10 - '@types/node': 18.11.18 - '@typescript-eslint/eslint-plugin': ^5.42.2-alpha - '@typescript-eslint/parser': ^5.42.2-alpha + '@types/eslint': ^8.21.3 + '@types/node': 18.15.5 + '@typescript-eslint/eslint-plugin': ^5.56.0 + '@typescript-eslint/parser': ^5.56.0 eslint: ^8.26.0 - eslint-config-prettier: ^8.6.0 - eslint-import-resolver-typescript: ^3.5.2 - eslint-plugin-import: ^2.26.0 + eslint-config-prettier: ^8.8.0 + eslint-import-resolver-typescript: ^3.5.3 + eslint-plugin-import: ^2.27.5 eslint-plugin-json: ^3.1.0 - eslint-plugin-jsonc: ^2.5.0 + eslint-plugin-jsonc: ^2.7.0 eslint-plugin-prettier: ^4.2.1 - eslint-plugin-simple-import-sort: ^8.0.0 + eslint-plugin-simple-import-sort: ^10.0.0 eslint-plugin-unused-imports: ^2.0.0 jsonc-eslint-parser: ^2.1.0 - prettier: ^2.8.1 + prettier: ^2.8.6 typescript: '*' dependencies: - '@types/eslint': 8.4.10 - '@typescript-eslint/eslint-plugin': 5.48.0_k73wpmdolxikpyqun3p36akaaq - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe - eslint: 8.31.0 - eslint-config-prettier: 8.6.0_eslint@8.31.0 - eslint-import-resolver-typescript: 3.5.2_ol7jqilc3wemtdbq3nzhywgxq4 - eslint-plugin-import: 2.26.0_cxu27kyieece4tnvunezm4whiq + '@types/eslint': 8.21.3 + '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + eslint: 8.36.0 + eslint-config-prettier: 8.8.0_eslint@8.36.0 + eslint-import-resolver-typescript: 3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy + eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq eslint-plugin-json: 3.1.0 - eslint-plugin-jsonc: 2.5.0_eslint@8.31.0 - eslint-plugin-prettier: 4.2.1_32m5uc2milwdw3tnkcq5del26y - eslint-plugin-simple-import-sort: 8.0.0_eslint@8.31.0 - eslint-plugin-unused-imports: 2.0.0_zgazubnvp3urkgs5b7mw2pde3m + eslint-plugin-jsonc: 2.7.0_eslint@8.36.0 + eslint-plugin-prettier: 4.2.1_ose2zoovovx4ulolhifz3tfzx4 + eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0 + eslint-plugin-unused-imports: 2.0.0_pjgbsoxltfjhart6hcjsvw66hu jsonc-eslint-parser: 2.1.0 - prettier: 2.8.1 - typescript: 4.9.4 + prettier: 2.8.6 + typescript: 5.0.2 devDependencies: - '@types/node': 18.11.18 + '@types/node': 18.15.5 workspace/json: specifiers: @@ -1126,7 +1134,7 @@ importers: '@starbeam-workspace/paths': workspace:^ '@starbeam-workspace/shared': workspace:^ '@starbeam/core-utils': workspace:^ - '@types/node': 18.11.18 + '@types/node': 18.15.5 '@types/shell-escape-tag': workspace:^ '@types/shell-split': workspace:^ '@types/split2': ^3.2.1 @@ -1155,7 +1163,7 @@ importers: wrap-ansi: 8.0.1 devDependencies: '@starbeam-dev/build-support': link:../build - '@types/node': 18.11.18 + '@types/node': 18.15.5 '@types/shell-escape-tag': link:../../@types/shell-escape-tag '@types/shell-split': link:../../@types/shell-split '@types/split2': 3.2.1 @@ -1183,7 +1191,7 @@ importers: depcheck: ^1.4.3 dirfilename: ^1.0.4 emoji-regex: ^10.2.1 - eslint: ^8.31.0 + eslint: ^8.36.0 esno: ^0.16.3 fast-glob: ^3.2.11 jsonc-parser: ^3.0.0 @@ -1208,7 +1216,7 @@ importers: depcheck: 1.4.3 dirfilename: 1.1.1 emoji-regex: 10.2.1 - eslint: 8.31.0 + eslint: 8.36.0 fast-glob: 3.2.12 node-pty: 0.10.1 prettier: 2.8.1 @@ -1283,44 +1291,44 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/compat-data/7.20.10: - resolution: {integrity: sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==} + /@babel/compat-data/7.21.0: + resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} engines: {node: '>=6.9.0'} dev: true - /@babel/core/7.20.7: - resolution: {integrity: sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw==} + /@babel/core/7.21.3: + resolution: {integrity: sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.0 '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.7 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.7 - '@babel/helper-module-transforms': 7.20.11 - '@babel/helpers': 7.20.7 - '@babel/parser': 7.20.7 + '@babel/generator': 7.21.3 + '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.21.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helpers': 7.21.0 + '@babel/parser': 7.21.3 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 - json5: 2.2.1 + json5: 2.2.3 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/eslint-parser/7.19.1_cbdx2nt4qlpatq6svgwvehmsk4: - resolution: {integrity: sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==} + /@babel/eslint-parser/7.21.3_pxuto7xgangxlusvzceggvrmde: + resolution: {integrity: sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: '@babel/core': '>=7.11.0' eslint: ^7.5.0 || ^8.0.0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.31.0 + eslint: 8.36.0 eslint-visitor-keys: 2.1.0 semver: 6.3.0 dev: true @@ -1329,7 +1337,7 @@ packages: resolution: {integrity: sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 '@jridgewell/gen-mapping': 0.3.2 jsesc: 2.5.2 @@ -1337,8 +1345,18 @@ packages: resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 + '@jridgewell/gen-mapping': 0.3.2 + jsesc: 2.5.2 + dev: true + + /@babel/generator/7.21.3: + resolution: {integrity: sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 jsesc: 2.5.2 dev: true @@ -1346,7 +1364,7 @@ packages: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 dev: true /@babel/helper-builder-binary-assignment-operator-visitor/7.18.9: @@ -1357,40 +1375,40 @@ packages: '@babel/types': 7.20.7 dev: true - /@babel/helper-compilation-targets/7.20.0_@babel+core@7.20.7: + /@babel/helper-compilation-targets/7.20.0_@babel+core@7.21.3: resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/compat-data': 7.20.1 - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-validator-option': 7.18.6 browserslist: 4.21.4 semver: 6.3.0 dev: true - /@babel/helper-compilation-targets/7.20.7_@babel+core@7.20.7: + /@babel/helper-compilation-targets/7.20.7_@babel+core@7.21.3: resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.20.10 - '@babel/core': 7.20.7 - '@babel/helper-validator-option': 7.18.6 + '@babel/compat-data': 7.21.0 + '@babel/core': 7.21.3 + '@babel/helper-validator-option': 7.21.0 browserslist: 4.21.4 lru-cache: 5.1.1 semver: 6.3.0 dev: true - /@babel/helper-create-class-features-plugin/7.20.7_@babel+core@7.20.7: + /@babel/helper-create-class-features-plugin/7.20.7_@babel+core@7.21.3: resolution: {integrity: sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.19.0 @@ -1402,24 +1420,43 @@ packages: - supports-color dev: true - /@babel/helper-create-regexp-features-plugin/7.19.0_@babel+core@7.20.7: + /@babel/helper-create-class-features-plugin/7.21.0_@babel+core@7.21.3: + resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/helper-split-export-declaration': 7.18.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-create-regexp-features-plugin/7.19.0_@babel+core@7.21.3: resolution: {integrity: sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 regexpu-core: 5.2.1 dev: true - /@babel/helper-define-polyfill-provider/0.3.3_@babel+core@7.20.7: + /@babel/helper-define-polyfill-provider/0.3.3_@babel+core@7.21.3: resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 debug: 4.3.4 lodash.debounce: 4.0.8 @@ -1437,7 +1474,7 @@ packages: resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 dev: true /@babel/helper-function-name/7.19.0: @@ -1447,6 +1484,14 @@ packages: '@babel/template': 7.20.7 '@babel/types': 7.20.7 + /@babel/helper-function-name/7.21.0: + resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/types': 7.21.3 + dev: true + /@babel/helper-hoist-variables/7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} engines: {node: '>=6.9.0'} @@ -1457,18 +1502,25 @@ packages: resolution: {integrity: sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 + dev: true + + /@babel/helper-member-expression-to-functions/7.21.0: + resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.3 dev: true /@babel/helper-module-imports/7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.2 + '@babel/types': 7.20.7 dev: true - /@babel/helper-module-transforms/7.20.11: - resolution: {integrity: sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==} + /@babel/helper-module-transforms/7.20.2: + resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 @@ -1483,8 +1535,8 @@ packages: - supports-color dev: true - /@babel/helper-module-transforms/7.20.2: - resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} + /@babel/helper-module-transforms/7.21.2: + resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 @@ -1493,8 +1545,8 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 transitivePeerDependencies: - supports-color dev: true @@ -1511,13 +1563,13 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.20.7: + /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-wrap-function': 7.19.0 @@ -1558,7 +1610,7 @@ packages: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.2 + '@babel/types': 7.20.7 /@babel/helper-string-parser/7.19.4: resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} @@ -1573,25 +1625,30 @@ packages: engines: {node: '>=6.9.0'} dev: true + /@babel/helper-validator-option/7.21.0: + resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-wrap-function/7.19.0: resolution: {integrity: sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/template': 7.20.7 '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/helpers/7.20.7: - resolution: {integrity: sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==} + /@babel/helpers/7.21.0: + resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.3 transitivePeerDependencies: - supports-color dev: true @@ -1617,459 +1674,467 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 /@babel/parser/7.20.7: resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 + + /@babel/parser/7.21.3: + resolution: {integrity: sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.21.3 + dev: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.20.7: + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.18.9_@babel+core@7.20.7: + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.20.7 + '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-async-generator-functions/7.20.1_@babel+core@7.20.7: + /@babel/plugin-proposal-async-generator-functions/7.20.1_@babel+core@7.21.3: resolution: {integrity: sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.7 + '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-class-static-block/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.7 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-decorators/7.20.7_@babel+core@7.20.7: - resolution: {integrity: sha512-JB45hbUweYpwAGjkiM7uCyXMENH2lG+9r3G2E+ttc2PRXAoEkpfd/KW5jDg4j8RS6tLtTG1jZi9LbHZVSfs1/A==} + /@babel/plugin-proposal-decorators/7.21.0_@babel+core@7.21.3: + resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.21.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/plugin-syntax-decorators': 7.19.0_@babel+core@7.20.7 + '@babel/plugin-syntax-decorators': 7.21.0_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-dynamic-import/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-dynamic-import/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.20.7: + /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.7 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.7 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-logical-assignment-operators/7.18.9_@babel+core@7.20.7: + /@babel/plugin-proposal-logical-assignment-operators/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.7 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.7 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-numeric-separator/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-numeric-separator/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.20.7 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-object-rest-spread/7.20.2_@babel+core@7.20.7: + /@babel/plugin-proposal-object-rest-spread/7.20.2_@babel+core@7.21.3: resolution: {integrity: sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/compat-data': 7.20.1 - '@babel/core': 7.20.7 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-transform-parameters': 7.20.3_@babel+core@7.20.7 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-transform-parameters': 7.20.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.20.7 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-optional-chaining/7.18.9_@babel+core@7.20.7: + /@babel/plugin-proposal-optional-chaining/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.7 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.21.3 dev: true - /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-property-in-object/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-private-property-in-object/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.20.7 + '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.7 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.20.7: + /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.20.7: + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.21.3: resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.20.7: + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.21.3: resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.20.7: + /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.21.3: resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-decorators/7.19.0_@babel+core@7.20.7: - resolution: {integrity: sha512-xaBZUEDntt4faL1yN8oIFlhfXeQAWJW7CLKYsHTUqriCUbj8xOra8bfxxKGi/UwExPFBuPdH4XfHc9rGQhrVkQ==} + /@babel/plugin-syntax-decorators/7.21.0_@babel+core@7.21.3: + resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.20.7: + /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.21.3: resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.20.7: + /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.20.7: + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.21.3: resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.20.7: + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.21.3: resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.20.7: + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.21.3: resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.20.7: + /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.21.3: resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.20.7: + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.21.3: resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.20.7: + /@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.21.3: resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-arrow-functions/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-arrow-functions/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-async-to-generator/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-async-to-generator/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.20.7 + '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-block-scoping/7.20.2_@babel+core@7.20.7: + /@babel/plugin-transform-block-scoping/7.20.2_@babel+core@7.21.3: resolution: {integrity: sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-classes/7.20.2_@babel+core@7.20.7: + /@babel/plugin-transform-classes/7.20.2_@babel+core@7.21.3: resolution: {integrity: sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.7 + '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.19.0 '@babel/helper-optimise-call-expression': 7.18.6 @@ -2081,120 +2146,120 @@ packages: - supports-color dev: true - /@babel/plugin-transform-computed-properties/7.18.9_@babel+core@7.20.7: + /@babel/plugin-transform-computed-properties/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-destructuring/7.20.2_@babel+core@7.20.7: + /@babel/plugin-transform-destructuring/7.20.2_@babel+core@7.21.3: resolution: {integrity: sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.20.7: + /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-for-of/7.18.8_@babel+core@7.20.7: + /@babel/plugin-transform-for-of/7.18.8_@babel+core@7.21.3: resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.20.7: + /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 '@babel/helper-function-name': 7.19.0 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-literals/7.18.9_@babel+core@7.20.7: + /@babel/plugin-transform-literals/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-modules-amd/7.19.6_@babel+core@7.20.7: + /@babel/plugin-transform-modules-amd/7.19.6_@babel+core@7.21.3: resolution: {integrity: sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-module-transforms': 7.20.2 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs/7.19.6_@babel+core@7.20.7: + /@babel/plugin-transform-modules-commonjs/7.19.6_@babel+core@7.21.3: resolution: {integrity: sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-module-transforms': 7.20.2 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-simple-access': 7.20.2 @@ -2202,13 +2267,13 @@ packages: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs/7.19.6_@babel+core@7.20.7: + /@babel/plugin-transform-modules-systemjs/7.19.6_@babel+core@7.21.3: resolution: {integrity: sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-module-transforms': 7.20.2 '@babel/helper-plugin-utils': 7.20.2 @@ -2217,380 +2282,373 @@ packages: - supports-color dev: true - /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-module-transforms': 7.20.2 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.19.1_@babel+core@7.20.7: + /@babel/plugin-transform-named-capturing-groups-regex/7.19.1_@babel+core@7.21.3: resolution: {integrity: sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-parameters/7.20.3_@babel+core@7.20.7: + /@babel/plugin-transform-parameters/7.20.3_@babel+core@7.21.3: resolution: {integrity: sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-react-display-name/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-react-display-name/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.21.3 dev: true - /@babel/plugin-transform-react-jsx/7.19.0_@babel+core@7.20.7: + /@babel/plugin-transform-react-jsx/7.19.0_@babel+core@7.21.3: resolution: {integrity: sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.7 + '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.21.3 '@babel/types': 7.20.2 dev: true - /@babel/plugin-transform-react-pure-annotations/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-react-pure-annotations/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-regenerator/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-regenerator/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 regenerator-transform: 0.15.0 dev: true - /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-runtime/7.19.6_@babel+core@7.20.7: - resolution: {integrity: sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==} + /@babel/plugin-transform-runtime/7.21.0_@babel+core@7.21.3: + resolution: {integrity: sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.7 - babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.7 - babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.7 + babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.21.3 + babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.21.3 + babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.21.3 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-spread/7.19.0_@babel+core@7.20.7: + /@babel/plugin-transform-spread/7.19.0_@babel+core@7.21.3: resolution: {integrity: sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 dev: true - /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.20.7: + /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.20.7: + /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.21.3: resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-typescript/7.20.2_@babel+core@7.20.7: - resolution: {integrity: sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag==} + /@babel/plugin-transform-typescript/7.21.3_@babel+core@7.21.3: + resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-create-class-features-plugin': 7.21.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.7 + '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.20.7: + /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.21.3: resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.20.7: + /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/preset-env/7.20.2_@babel+core@7.20.7: + /@babel/preset-env/7.20.2_@babel+core@7.21.3: resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/compat-data': 7.20.1 - '@babel/core': 7.20.7 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-proposal-async-generator-functions': 7.20.1_@babel+core@7.20.7 - '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-class-static-block': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-dynamic-import': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-export-namespace-from': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-proposal-json-strings': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-logical-assignment-operators': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-numeric-separator': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-object-rest-spread': 7.20.2_@babel+core@7.20.7 - '@babel/plugin-proposal-optional-catch-binding': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-private-property-in-object': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.7 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.20.7 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.7 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-import-assertions': 7.20.0_@babel+core@7.20.7 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.7 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.20.7 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.7 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.7 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.7 - '@babel/plugin-transform-arrow-functions': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-async-to-generator': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-block-scoped-functions': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-block-scoping': 7.20.2_@babel+core@7.20.7 - '@babel/plugin-transform-classes': 7.20.2_@babel+core@7.20.7 - '@babel/plugin-transform-computed-properties': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-transform-destructuring': 7.20.2_@babel+core@7.20.7 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-duplicate-keys': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-transform-exponentiation-operator': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-for-of': 7.18.8_@babel+core@7.20.7 - '@babel/plugin-transform-function-name': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-transform-literals': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-transform-member-expression-literals': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-modules-amd': 7.19.6_@babel+core@7.20.7 - '@babel/plugin-transform-modules-commonjs': 7.19.6_@babel+core@7.20.7 - '@babel/plugin-transform-modules-systemjs': 7.19.6_@babel+core@7.20.7 - '@babel/plugin-transform-modules-umd': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1_@babel+core@7.20.7 - '@babel/plugin-transform-new-target': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-object-super': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-parameters': 7.20.3_@babel+core@7.20.7 - '@babel/plugin-transform-property-literals': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-regenerator': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-reserved-words': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-shorthand-properties': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-spread': 7.19.0_@babel+core@7.20.7 - '@babel/plugin-transform-sticky-regex': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-template-literals': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-transform-typeof-symbol': 7.18.9_@babel+core@7.20.7 - '@babel/plugin-transform-unicode-escapes': 7.18.10_@babel+core@7.20.7 - '@babel/plugin-transform-unicode-regex': 7.18.6_@babel+core@7.20.7 - '@babel/preset-modules': 0.1.5_@babel+core@7.20.7 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-proposal-async-generator-functions': 7.20.1_@babel+core@7.21.3 + '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-class-static-block': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-dynamic-import': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-export-namespace-from': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-proposal-json-strings': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-logical-assignment-operators': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-numeric-separator': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-object-rest-spread': 7.20.2_@babel+core@7.21.3 + '@babel/plugin-proposal-optional-catch-binding': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-private-property-in-object': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.21.3 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.21.3 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.21.3 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-import-assertions': 7.20.0_@babel+core@7.21.3 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.21.3 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.21.3 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.21.3 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.21.3 + '@babel/plugin-transform-arrow-functions': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-async-to-generator': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-block-scoped-functions': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-block-scoping': 7.20.2_@babel+core@7.21.3 + '@babel/plugin-transform-classes': 7.20.2_@babel+core@7.21.3 + '@babel/plugin-transform-computed-properties': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-transform-destructuring': 7.20.2_@babel+core@7.21.3 + '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-duplicate-keys': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-transform-exponentiation-operator': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-for-of': 7.18.8_@babel+core@7.21.3 + '@babel/plugin-transform-function-name': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-transform-literals': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-transform-member-expression-literals': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-modules-amd': 7.19.6_@babel+core@7.21.3 + '@babel/plugin-transform-modules-commonjs': 7.19.6_@babel+core@7.21.3 + '@babel/plugin-transform-modules-systemjs': 7.19.6_@babel+core@7.21.3 + '@babel/plugin-transform-modules-umd': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1_@babel+core@7.21.3 + '@babel/plugin-transform-new-target': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-object-super': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-parameters': 7.20.3_@babel+core@7.21.3 + '@babel/plugin-transform-property-literals': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-regenerator': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-reserved-words': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-shorthand-properties': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-spread': 7.19.0_@babel+core@7.21.3 + '@babel/plugin-transform-sticky-regex': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-template-literals': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-transform-typeof-symbol': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-transform-unicode-escapes': 7.18.10_@babel+core@7.21.3 + '@babel/plugin-transform-unicode-regex': 7.18.6_@babel+core@7.21.3 + '@babel/preset-modules': 0.1.5_@babel+core@7.21.3 '@babel/types': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.7 - babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.7 - babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.7 + babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.21.3 + babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.21.3 + babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.21.3 core-js-compat: 3.26.0 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/preset-modules/0.1.5_@babel+core@7.20.7: + /@babel/preset-modules/0.1.5_@babel+core@7.21.3: resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.20.7 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.21.3 '@babel/types': 7.20.2 esutils: 2.0.3 dev: true - /@babel/preset-react/7.18.6_@babel+core@7.20.7: + /@babel/preset-react/7.18.6_@babel+core@7.21.3: resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-react-display-name': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.20.7 - '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.20.7 - '@babel/plugin-transform-react-pure-annotations': 7.18.6_@babel+core@7.20.7 + '@babel/plugin-transform-react-display-name': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.21.3 + '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-react-pure-annotations': 7.18.6_@babel+core@7.21.3 dev: true - /@babel/preset-typescript/7.18.6_@babel+core@7.20.7: - resolution: {integrity: sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==} + /@babel/preset-typescript/7.21.0_@babel+core@7.21.3: + resolution: {integrity: sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 + '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-typescript': 7.20.2_@babel+core@7.20.7 + '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-transform-typescript': 7.21.3_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true - /@babel/runtime-corejs3/7.20.7: - resolution: {integrity: sha512-jr9lCZ4RbRQmCR28Q8U8Fu49zvFqLxTY9AMOUz+iyMohMoAgpEcVxY+wJNay99oXOpOcCTODkk70NDN2aaJEeg==} - engines: {node: '>=6.9.0'} - dependencies: - core-js-pure: 3.27.1 - regenerator-runtime: 0.13.11 - dev: true - - /@babel/runtime/7.20.7: - resolution: {integrity: sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==} + /@babel/runtime/7.21.0: + resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.11 @@ -2601,7 +2659,7 @@ packages: dependencies: '@babel/code-frame': 7.18.6 '@babel/parser': 7.20.7 - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 /@babel/traverse/7.20.1: resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} @@ -2628,11 +2686,11 @@ packages: '@babel/code-frame': 7.18.6 '@babel/generator': 7.20.7 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 '@babel/parser': 7.20.7 - '@babel/types': 7.20.7 + '@babel/types': 7.21.3 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: @@ -2657,6 +2715,24 @@ packages: - supports-color dev: true + /@babel/traverse/7.21.3: + resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.21.3 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/parser': 7.21.3 + '@babel/types': 7.21.3 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/types/7.20.2: resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==} engines: {node: '>=6.9.0'} @@ -2673,10 +2749,18 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 + /@babel/types/7.21.3: + resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + /@changesets/apply-release-plan/6.1.3: resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/config': 2.3.0 '@changesets/get-version-range-type': 0.3.2 '@changesets/git': 2.0.0 @@ -2686,7 +2770,7 @@ packages: fs-extra: 7.0.1 lodash.startcase: 4.4.0 outdent: 0.5.0 - prettier: 2.8.1 + prettier: 2.8.6 resolve-from: 5.0.0 semver: 5.7.1 dev: true @@ -2694,7 +2778,7 @@ packages: /@changesets/assemble-release-plan/5.2.3: resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/errors': 0.1.4 '@changesets/get-dependents-graph': 1.3.5 '@changesets/types': 5.2.1 @@ -2708,11 +2792,11 @@ packages: '@changesets/types': 5.2.1 dev: true - /@changesets/cli/2.26.0: - resolution: {integrity: sha512-0cbTiDms+ICTVtEwAFLNW0jBNex9f5+fFv3I771nBvdnV/mOjd1QJ4+f8KtVSOrwD9SJkk9xbDkWFb0oXd8d1Q==} + /@changesets/cli/2.26.1: + resolution: {integrity: sha512-XnTa+b51vt057fyAudvDKGB0Sh72xutQZNAdXkCqPBKO2zvs2yYZx5hFZj1u9cbtpwM6Sxtcr02/FQJfZOzemQ==} hasBin: true dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/apply-release-plan': 6.1.3 '@changesets/assemble-release-plan': 5.2.3 '@changesets/changelog-git': 0.1.14 @@ -2778,7 +2862,7 @@ packages: /@changesets/get-release-plan/3.0.16: resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/assemble-release-plan': 5.2.3 '@changesets/config': 2.3.0 '@changesets/pre': 1.0.14 @@ -2794,7 +2878,7 @@ packages: /@changesets/git/2.0.0: resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -2819,7 +2903,7 @@ packages: /@changesets/pre/1.0.14: resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -2829,7 +2913,7 @@ packages: /@changesets/read/0.5.9: resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/git': 2.0.0 '@changesets/logger': 0.0.5 '@changesets/parse': 0.3.16 @@ -2850,11 +2934,11 @@ packages: /@changesets/write/0.2.3: resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 - prettier: 2.8.1 + prettier: 2.8.6 dev: true /@colors/colors/1.5.0: @@ -2863,8 +2947,8 @@ packages: requiresBuild: true optional: true - /@crxjs/vite-plugin/2.0.0-beta.12: - resolution: {integrity: sha512-F2SNF8aKGXF1mqg0EQisgdK1fgUud9BR52rpf9iPEKGH+41//t+qj9aRls3+iUOx3niNYujIXTMyrdyPpSzs9g==} + /@crxjs/vite-plugin/2.0.0-beta.15: + resolution: {integrity: sha512-3lDltBqr41BZpJRidbXnKiWwvvfpb8CQ0SKEBW1XsnKTzP9ZcJnZuSoTizBxd6Hx2VPrGFooPjuh+ohQ3QIoHg==} dependencies: '@rollup/pluginutils': 4.2.1 '@webcomponents/custom-elements': 1.5.1 @@ -2924,12 +3008,12 @@ packages: get-tsconfig: 4.2.0 dev: true - /@esbuild-plugins/node-globals-polyfill/0.1.1_esbuild@0.16.13: + /@esbuild-plugins/node-globals-polyfill/0.1.1_esbuild@0.17.12: resolution: {integrity: sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==} peerDependencies: esbuild: '*' dependencies: - esbuild: 0.16.13 + esbuild: 0.17.12 /@esbuild/android-arm/0.15.13: resolution: {integrity: sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==} @@ -2940,80 +3024,80 @@ packages: dev: true optional: true - /@esbuild/android-arm/0.16.13: - resolution: {integrity: sha512-JmtqThupn9Yf+FzANE+GG73ASUkssnPwOsndUElhp23685QzRK+MO1UompOlBaXV9D5FTuYcPnw7p4mCq2YbZQ==} + /@esbuild/android-arm/0.17.12: + resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==} engines: {node: '>=12'} cpu: [arm] os: [android] requiresBuild: true optional: true - /@esbuild/android-arm64/0.16.13: - resolution: {integrity: sha512-r4xetsd1ez1NF9/9R2f9Q6AlxqiZLwUqo7ICOcvEVwopVkXUcspIjEbJk0EVTgT6Cp5+ymzGPT6YNV0ievx4yA==} + /@esbuild/android-arm64/0.17.12: + resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true optional: true - /@esbuild/android-x64/0.16.13: - resolution: {integrity: sha512-hKt1bFht/Vtp0xJ0ZVzFMnPy1y1ycmM3KNnp3zsyZfQmw7nhs2WLO4vxdR5YG+6RsHKCb2zbZ3VwlC0Tij0qyA==} + /@esbuild/android-x64/0.17.12: + resolution: {integrity: sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==} engines: {node: '>=12'} cpu: [x64] os: [android] requiresBuild: true optional: true - /@esbuild/darwin-arm64/0.16.13: - resolution: {integrity: sha512-ogrVuNi2URocrr3Ps20f075EMm9V7IeenOi9FRj4qdbT6mQlwLuP4l90PW2iBrKERx0oRkcZprEUNsz/3xd7ww==} + /@esbuild/darwin-arm64/0.17.12: + resolution: {integrity: sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /@esbuild/darwin-x64/0.16.13: - resolution: {integrity: sha512-Agajik9SBGiKD7FPXE+ExW6x3MgA/dUdpZnXa9y1tyfE4lKQx+eQiknSdrBnWPeqa9wL0AOvkhghmYhpVkyqkA==} + /@esbuild/darwin-x64/0.17.12: + resolution: {integrity: sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==} engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /@esbuild/freebsd-arm64/0.16.13: - resolution: {integrity: sha512-KxMO3/XihBcHM+xQUM6nQZO1SgQuOsd1DCnKF1a4SIf/i5VD45vrqN3k8ePgFrEbMi7m5JeGmvNqwJXinF0a4Q==} + /@esbuild/freebsd-arm64/0.17.12: + resolution: {integrity: sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true optional: true - /@esbuild/freebsd-x64/0.16.13: - resolution: {integrity: sha512-Ez15oqV1vwvZ30cVLeBW14BsWq/fdWNQGMOxxqaSJVQVLqHhvgfQ7gxGDiN9tpJdeQhqJO+Q0r02/Tce5+USNg==} + /@esbuild/freebsd-x64/0.17.12: + resolution: {integrity: sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true optional: true - /@esbuild/linux-arm/0.16.13: - resolution: {integrity: sha512-18dLd2L3mda+iFj6sswyBMSh2UwniamD9M4DwPv8VM+9apRFlQ5IGKxBdumnTuOI4NvwwAernmUseWhYQ9k+rg==} + /@esbuild/linux-arm/0.17.12: + resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==} engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm64/0.16.13: - resolution: {integrity: sha512-qi5n7KwcGViyJeZeQnu8fB6dC3Mlm5PGaqSv2HhQDDx/MPvVfQGNMcv7zcBL4qk3FkuWhGVwXkjQ76x7R0PWlA==} + /@esbuild/linux-arm64/0.17.12: + resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==} engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ia32/0.16.13: - resolution: {integrity: sha512-2489Xad9sr+6GD7nB913fUqpCsSwVwgskkQTq4Or2mZntSPYPebyJm8l1YruHo7oqYMTGV6RiwGE4gRo3H+EPQ==} + /@esbuild/linux-ia32/0.17.12: + resolution: {integrity: sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -3029,102 +3113,115 @@ packages: dev: true optional: true - /@esbuild/linux-loong64/0.16.13: - resolution: {integrity: sha512-x8KplRu9Y43Px8I9YS+sPBwQ+fw44Mvp2BPVADopKDWz+h3fcj1BvRU58kxb89WObmwKX9sWdtYzepL4Fmx03A==} + /@esbuild/linux-loong64/0.17.12: + resolution: {integrity: sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==} engines: {node: '>=12'} cpu: [loong64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-mips64el/0.16.13: - resolution: {integrity: sha512-qhhdWph9FLwD9rVVC/nUf7k2U4NZIA6/mGx0B7+O6PFV0GjmPA2E3zDQ4NUjq9P26E0DeAZy9akH9dYcUBRU7A==} + /@esbuild/linux-mips64el/0.17.12: + resolution: {integrity: sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ppc64/0.16.13: - resolution: {integrity: sha512-cVWAPKsrRVxI1jCeJHnYSbE3BrEU+pZTZK2gfao9HRxuc+3m4+RLfs3EVEpGLmMKEcWfVCB9wZ3yNxnknutGKQ==} + /@esbuild/linux-ppc64/0.17.12: + resolution: {integrity: sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-riscv64/0.16.13: - resolution: {integrity: sha512-Agb7dbRyZWnmPn5Vvf0eyqaEUqSsaIUwwyInu2EoFTaIDRp093QU2M5alUyOooMLkRbD1WvqQNwx08Z/g+SAcQ==} + /@esbuild/linux-riscv64/0.17.12: + resolution: {integrity: sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-s390x/0.16.13: - resolution: {integrity: sha512-AqRBIrc/+kl08ahliNG+EyU+j41wIzQfwBTKpi80cCDiYvYFPuXjvzZsD9muiu58Isj0RVni9VgC4xK/AnSW4g==} + /@esbuild/linux-s390x/0.17.12: + resolution: {integrity: sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==} engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-x64/0.16.13: - resolution: {integrity: sha512-S4wn2BimuhPcoArRtVrdHUKIymCCZcYAXQE47kUiX4yrUrEX2/ifn5eKNbZ5c1jJKUlh1gC2ESIN+iw3wQax3g==} + /@esbuild/linux-x64/0.17.12: + resolution: {integrity: sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==} engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@esbuild/netbsd-x64/0.16.13: - resolution: {integrity: sha512-2c8JWgfUMlQHTdaR5X3xNMwqOyad8kgeCupuVkdm3QkUOzGREjlTETQsK6oHifocYzDCo9FeKcUwsK356SdR+g==} + /@esbuild/netbsd-x64/0.17.12: + resolution: {integrity: sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true optional: true - /@esbuild/openbsd-x64/0.16.13: - resolution: {integrity: sha512-Bwh+PmKD/LK+xBjqIpnYnKYj0fIyQJ0YpRxsn0F+WfzvQ2OA+GKDlf8AHosiCns26Q4Dje388jQVwfOBZ1GaFw==} + /@esbuild/openbsd-x64/0.17.12: + resolution: {integrity: sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true optional: true - /@esbuild/sunos-x64/0.16.13: - resolution: {integrity: sha512-8wwk6f9XGnhrF94/DBdFM4Xm1JeCyGTCj67r516VS9yvBVQf3Rar54L+XPVDs/oZOokwH+XsktrgkuTMAmjntg==} + /@esbuild/sunos-x64/0.17.12: + resolution: {integrity: sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true optional: true - /@esbuild/win32-arm64/0.16.13: - resolution: {integrity: sha512-Jmwbp/5ArLCiRAHC33ODfcrlIcbP/exXkOEUVkADNJC4e/so2jm+i8IQFvVX/lA2GWvK3GdgcN0VFfp9YITAbg==} + /@esbuild/win32-arm64/0.17.12: + resolution: {integrity: sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /@esbuild/win32-ia32/0.16.13: - resolution: {integrity: sha512-AX6WjntGjhJHzrPSVvjMD7grxt41koHfAOx6lxLorrpDwwIKKPaGDASPZgvFIZHTbwhOtILW6vAXxYPDsKpDJA==} + /@esbuild/win32-ia32/0.17.12: + resolution: {integrity: sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /@esbuild/win32-x64/0.16.13: - resolution: {integrity: sha512-A+U4gM6OOkPS03UgVU08GTpAAAxPsP/8Z4FmneGo4TaVSD99bK9gVJXlqUEPMO/htFXEAht2O6pX4ErtLY5tVg==} + /@esbuild/win32-x64/0.17.12: + resolution: {integrity: sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==} engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true optional: true + /@eslint-community/eslint-utils/4.3.0_eslint@8.36.0: + resolution: {integrity: sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.36.0 + eslint-visitor-keys: 3.3.0 + + /@eslint-community/regexpp/4.4.0: + resolution: {integrity: sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + /@eslint/eslintrc/1.4.1: resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3140,6 +3237,27 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color + dev: false + + /@eslint/eslintrc/2.0.1: + resolution: {integrity: sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.5.0 + globals: 13.19.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + /@eslint/js/8.36.0: + resolution: {integrity: sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} /@faker-js/faker/7.6.0: resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} @@ -3199,8 +3317,8 @@ packages: /@manypkg/find-root/1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: - '@babel/runtime': 7.20.7 - '@types/node': 18.11.18 + '@babel/runtime': 7.21.0 + '@types/node': 18.15.5 find-up: 4.1.0 fs-extra: 8.1.0 dev: true @@ -3208,7 +3326,7 @@ packages: /@manypkg/get-packages/1.1.3: resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -3253,7 +3371,7 @@ packages: open: 8.4.0 picocolors: 1.0.0 tiny-glob: 0.2.9 - tslib: 2.4.1 + tslib: 2.5.0 /@polka/url/1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} @@ -3410,12 +3528,12 @@ packages: engines: {node: '>=12'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@types/aria-query': 4.2.2 aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.14 - lz-string: 1.4.4 + lz-string: 1.5.0 pretty-format: 27.5.1 dev: true @@ -3424,7 +3542,7 @@ packages: engines: {node: '>=12'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@types/aria-query': 5.0.1 aria-query: 5.1.3 chalk: 4.1.2 @@ -3433,6 +3551,20 @@ packages: pretty-format: 27.5.1 dev: false + /@testing-library/dom/9.0.1: + resolution: {integrity: sha512-fTOVsMY9QLFCCXRHG3Ese6cMH5qIWwSbgxZsgeF5TNsy81HKaZ4kgehnSF8FsR3OF+numlIV2YcU79MzbnhSig==} + engines: {node: '>=14'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/runtime': 7.21.0 + '@types/aria-query': 5.0.1 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.14 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: true + /@testing-library/preact/3.2.2_preact@10.11.3: resolution: {integrity: sha512-mMPEp/9TOOqf3QqDHY02ieGFfRbi8fAxZvRifn+vOzrdNcCR1zchwPA6BvqXG3wAweRan4QJioYgEc1cePeC3g==} engines: {node: '>= 12'} @@ -3450,13 +3582,27 @@ packages: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 '@testing-library/dom': 8.19.0 '@types/react-dom': 18.0.10 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 dev: true + /@testing-library/react/14.0.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} + engines: {node: '>=14'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.21.0 + '@testing-library/dom': 9.0.1 + '@types/react-dom': 18.0.10 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: true + /@tootallnate/once/2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} @@ -3472,20 +3618,17 @@ packages: /@types/aria-query/5.0.1: resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} - dev: false /@types/chai-subset/1.3.3: resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} dependencies: '@types/chai': 4.3.4 - dev: true /@types/chai/4.3.4: resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} - dev: true - /@types/eslint/8.4.10: - resolution: {integrity: sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==} + /@types/eslint/8.21.3: + resolution: {integrity: sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==} dependencies: '@types/estree': 1.0.0 '@types/json-schema': 7.0.11 @@ -3497,13 +3640,13 @@ packages: resolution: {integrity: sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 18.11.18 + '@types/node': 18.15.5 dev: true /@types/hoist-non-react-statics/3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: - '@types/react': 18.0.26 + '@types/react': 18.0.28 hoist-non-react-statics: 3.3.2 dev: true @@ -3521,6 +3664,7 @@ packages: /@types/minimatch/3.0.5: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + dev: false /@types/minimatch/5.1.2: resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} @@ -3530,8 +3674,8 @@ packages: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node/18.11.18: - resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + /@types/node/18.15.5: + resolution: {integrity: sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==} /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -3568,7 +3712,7 @@ packages: /@types/react-transition-group/4.4.5: resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==} dependencies: - '@types/react': 18.0.26 + '@types/react': 18.0.28 dev: true /@types/react/18.0.26: @@ -3579,6 +3723,14 @@ packages: csstype: 3.1.1 dev: true + /@types/react/18.0.28: + resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==} + dependencies: + '@types/prop-types': 15.7.5 + '@types/scheduler': 0.16.2 + csstype: 3.1.1 + dev: true + /@types/resolve/1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: false @@ -3598,13 +3750,13 @@ packages: resolution: {integrity: sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==} dependencies: '@types/glob': 8.0.0 - '@types/node': 18.11.18 + '@types/node': 18.15.5 dev: true /@types/split2/3.2.1: resolution: {integrity: sha512-7uz3yU+LooBq4yNOzlZD9PU9/1Eu0rTD1MjQ6apOVEoHsPrMUrFw7W8XrvWtesm2vK67SBK9AyJcOXtMpl9bgQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.15.5 dev: true /@types/styled-components/5.1.26: @@ -3623,8 +3775,8 @@ packages: resolution: {integrity: sha512-cjwgM6WWy9YakrQ36Pq0vg5XoNblVEaNq+/pHngKl4GyyDIxTeskPoG+tp4LsRk0lHrA4LaLJqlvYridi7mzlw==} dev: true - /@typescript-eslint/eslint-plugin/5.48.0_k73wpmdolxikpyqun3p36akaaq: - resolution: {integrity: sha512-SVLafp0NXpoJY7ut6VFVUU9I+YeFsDzeQwtK0WZ+xbRN3mtxJ08je+6Oi2N89qDn087COdO0u3blKZNv9VetRQ==} + /@typescript-eslint/eslint-plugin/5.56.0_2hcjazgfnbtq42tcc73br2vup4: + resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -3634,23 +3786,24 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe - '@typescript-eslint/scope-manager': 5.48.0 - '@typescript-eslint/type-utils': 5.48.0_iukboom6ndih5an6iafl45j2fe - '@typescript-eslint/utils': 5.48.0_iukboom6ndih5an6iafl45j2fe + '@eslint-community/regexpp': 4.4.0 + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/scope-manager': 5.56.0 + '@typescript-eslint/type-utils': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/utils': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu debug: 4.3.4 - eslint: 8.31.0 + eslint: 8.36.0 + grapheme-splitter: 1.0.4 ignore: 5.2.0 natural-compare-lite: 1.4.0 - regexpp: 3.2.0 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.4 - typescript: 4.9.4 + tsutils: 3.21.0_typescript@5.0.2 + typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/parser/5.48.0_iukboom6ndih5an6iafl45j2fe: - resolution: {integrity: sha512-1mxNA8qfgxX8kBvRDIHEzrRGrKHQfQlbW6iHyfHYS0Q4X1af+S6mkLNtgCOsGVl8+/LUPrqdHMssAemkrQ01qg==} + /@typescript-eslint/parser/5.56.0_j4766f7ecgqbon3u7zlxn5zszu: + resolution: {integrity: sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3659,24 +3812,24 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.48.0 - '@typescript-eslint/types': 5.48.0 - '@typescript-eslint/typescript-estree': 5.48.0_typescript@4.9.4 + '@typescript-eslint/scope-manager': 5.56.0 + '@typescript-eslint/types': 5.56.0 + '@typescript-eslint/typescript-estree': 5.56.0_typescript@5.0.2 debug: 4.3.4 - eslint: 8.31.0 - typescript: 4.9.4 + eslint: 8.36.0 + typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/scope-manager/5.48.0: - resolution: {integrity: sha512-0AA4LviDtVtZqlyUQnZMVHydDATpD9SAX/RC5qh6cBd3xmyWvmXYF+WT1oOmxkeMnWDlUVTwdODeucUnjz3gow==} + /@typescript-eslint/scope-manager/5.56.0: + resolution: {integrity: sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.48.0 - '@typescript-eslint/visitor-keys': 5.48.0 + '@typescript-eslint/types': 5.56.0 + '@typescript-eslint/visitor-keys': 5.56.0 - /@typescript-eslint/type-utils/5.48.0_iukboom6ndih5an6iafl45j2fe: - resolution: {integrity: sha512-vbtPO5sJyFjtHkGlGK4Sthmta0Bbls4Onv0bEqOGm7hP9h8UpRsHJwsrCiWtCUndTRNQO/qe6Ijz9rnT/DB+7g==} + /@typescript-eslint/type-utils/5.56.0_j4766f7ecgqbon3u7zlxn5zszu: + resolution: {integrity: sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -3685,21 +3838,21 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.48.0_typescript@4.9.4 - '@typescript-eslint/utils': 5.48.0_iukboom6ndih5an6iafl45j2fe + '@typescript-eslint/typescript-estree': 5.56.0_typescript@5.0.2 + '@typescript-eslint/utils': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu debug: 4.3.4 - eslint: 8.31.0 - tsutils: 3.21.0_typescript@4.9.4 - typescript: 4.9.4 + eslint: 8.36.0 + tsutils: 3.21.0_typescript@5.0.2 + typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/types/5.48.0: - resolution: {integrity: sha512-UTe67B0Ypius0fnEE518NB2N8gGutIlTojeTg4nt0GQvikReVkurqxd2LvYa9q9M5MQ6rtpNyWTBxdscw40Xhw==} + /@typescript-eslint/types/5.56.0: + resolution: {integrity: sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@typescript-eslint/typescript-estree/5.48.0_typescript@4.9.4: - resolution: {integrity: sha512-7pjd94vvIjI1zTz6aq/5wwE/YrfIyEPLtGJmRfyNR9NYIW+rOvzzUv3Cmq2hRKpvt6e9vpvPUQ7puzX7VSmsEw==} + /@typescript-eslint/typescript-estree/5.56.0_typescript@5.0.2: + resolution: {integrity: sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -3707,51 +3860,80 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.48.0 - '@typescript-eslint/visitor-keys': 5.48.0 + '@typescript-eslint/types': 5.56.0 + '@typescript-eslint/visitor-keys': 5.56.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.4 - typescript: 4.9.4 + tsutils: 3.21.0_typescript@5.0.2 + typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/utils/5.48.0_iukboom6ndih5an6iafl45j2fe: - resolution: {integrity: sha512-x2jrMcPaMfsHRRIkL+x96++xdzvrdBCnYRd5QiW5Wgo1OB4kDYPbC1XjWP/TNqlfK93K/lUL92erq5zPLgFScQ==} + /@typescript-eslint/utils/5.56.0_j4766f7ecgqbon3u7zlxn5zszu: + resolution: {integrity: sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: + '@eslint-community/eslint-utils': 4.3.0_eslint@8.36.0 '@types/json-schema': 7.0.11 '@types/semver': 7.3.13 - '@typescript-eslint/scope-manager': 5.48.0 - '@typescript-eslint/types': 5.48.0 - '@typescript-eslint/typescript-estree': 5.48.0_typescript@4.9.4 - eslint: 8.31.0 + '@typescript-eslint/scope-manager': 5.56.0 + '@typescript-eslint/types': 5.56.0 + '@typescript-eslint/typescript-estree': 5.56.0_typescript@5.0.2 + eslint: 8.36.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.31.0 semver: 7.3.8 transitivePeerDependencies: - supports-color - typescript - /@typescript-eslint/visitor-keys/5.48.0: - resolution: {integrity: sha512-5motVPz5EgxQ0bHjut3chzBkJ3Z3sheYVcSwS5BpHZpLqSptSmELNtGixmgj65+rIfhvtQTz5i9OP2vtzdDH7Q==} + /@typescript-eslint/visitor-keys/5.56.0: + resolution: {integrity: sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.48.0 + '@typescript-eslint/types': 5.56.0 eslint-visitor-keys: 3.3.0 - /@vitest/ui/0.26.3: - resolution: {integrity: sha512-GekIZekLQVL765LmQObHai7Q3U+BWD0nxJVK1yV8VPcs6H/6EAnNuEZ8tFq87jCxyHEZ3zmOrX6uPmG65gBVrA==} + /@vitest/expect/0.29.7: + resolution: {integrity: sha512-UtG0tW0DP6b3N8aw7PHmweKDsvPv4wjGvrVZW7OSxaFg76ShtVdMiMcUkZJgCE8QWUmhwaM0aQhbbVLo4F4pkA==} + dependencies: + '@vitest/spy': 0.29.7 + '@vitest/utils': 0.29.7 + chai: 4.3.7 + + /@vitest/runner/0.29.7: + resolution: {integrity: sha512-Yt0+csM945+odOx4rjZSjibQfl2ymxqVsmYz6sO2fiO5RGPYDFCo60JF6tLL9pz4G/kjY4irUxadeB1XT+H1jg==} + dependencies: + '@vitest/utils': 0.29.7 + p-limit: 4.0.0 + pathe: 1.1.0 + + /@vitest/spy/0.29.7: + resolution: {integrity: sha512-IalL0iO6A6Xz8hthR8sctk6ZS//zVBX48EiNwQguYACdgdei9ZhwMaBFV70mpmeYAFCRAm+DpoFHM5470Im78A==} + dependencies: + tinyspy: 1.0.2 + + /@vitest/ui/0.29.7: + resolution: {integrity: sha512-KeOztcAldlFU5i8DKCQcmGrih1dVowurZy/9iPz5JyQdPJzej+nW1nI4nYvc4ZmUtA8+IAe9uViqnU7IXc1RNw==} dependencies: fast-glob: 3.2.12 flatted: 3.2.7 + pathe: 1.1.0 + picocolors: 1.0.0 sirv: 2.0.2 dev: true + /@vitest/utils/0.29.7: + resolution: {integrity: sha512-vNgGadp2eE5XKCXtZXL5UyNEDn68npSct75OC9AlELenSK0DiV1Mb9tfkwJHKjRb69iek+e79iipoJx8+s3SdA==} + dependencies: + cli-truncate: 3.1.0 + diff: 5.1.0 + loupe: 2.3.6 + pretty-format: 27.5.1 + /@vue/compiler-core/3.2.41: resolution: {integrity: sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==} dependencies: @@ -3819,7 +4001,7 @@ packages: /acorn-globals/7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 acorn-walk: 8.2.0 /acorn-jsx/5.3.2_acorn@8.8.1: @@ -3828,6 +4010,14 @@ packages: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.8.1 + dev: false + + /acorn-jsx/5.3.2_acorn@8.8.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.2 /acorn-walk/8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} @@ -3838,6 +4028,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /acorn/8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + /agent-base/6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -3910,18 +4105,10 @@ packages: /argparse/2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - /aria-query/4.2.2: - resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} - engines: {node: '>=6.0'} - dependencies: - '@babel/runtime': 7.20.7 - '@babel/runtime-corejs3': 7.20.7 - dev: true - /aria-query/5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} dependencies: - deep-equal: 2.1.0 + deep-equal: 2.2.0 /array-differ/3.0.0: resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} @@ -3933,9 +4120,9 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 is-string: 1.0.7 /array-union/2.1.0: @@ -3947,7 +4134,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 es-shim-unscopables: 1.0.0 @@ -3956,19 +4143,18 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 es-shim-unscopables: 1.0.0 - dev: true /array.prototype.tosorted/1.1.1: resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 es-shim-unscopables: 1.0.0 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 dev: true /arrify/1.0.1: @@ -3989,7 +4175,6 @@ packages: /assertion-error/1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true /ast-types-flow/0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} @@ -4002,8 +4187,8 @@ packages: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} - /axe-core/4.6.1: - resolution: {integrity: sha512-lCZN5XRuOnpG4bpMq8v0khrWtUOn+i8lZSb6wHZH56ZfbIEv6XwJV84AAueh9/zi7qPVJ/E4yz6fmsiyOmXR4w==} + /axe-core/4.6.3: + resolution: {integrity: sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==} engines: {node: '>=4'} dev: true @@ -4016,42 +4201,44 @@ packages: transitivePeerDependencies: - debug - /axobject-query/2.2.0: - resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} + /axobject-query/3.1.1: + resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} + dependencies: + deep-equal: 2.2.0 dev: true - /babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.20.7: + /babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.21.3: resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/compat-data': 7.20.1 - '@babel/core': 7.20.7 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.21.3 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-corejs3/0.6.0_@babel+core@7.20.7: + /babel-plugin-polyfill-corejs3/0.6.0_@babel+core@7.21.3: resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.21.3 core-js-compat: 3.26.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-regenerator/0.4.1_@babel+core@7.20.7: + /babel-plugin-polyfill-regenerator/0.4.1_@babel+core@7.21.3: resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.7 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.7 + '@babel/core': 7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.21.3 transitivePeerDependencies: - supports-color dev: true @@ -4173,11 +4360,15 @@ packages: engines: {node: '>=6'} dev: false + /cac/6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + /call-bind/1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 /callsites/3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -4229,7 +4420,6 @@ packages: loupe: 2.3.6 pathval: 1.1.1 type-detect: 4.0.8 - dev: true /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -4256,7 +4446,6 @@ packages: /check-error/1.0.2: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} - dev: true /cheerio-select/2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -4278,7 +4467,7 @@ packages: domhandler: 5.0.3 domutils: 3.0.1 htmlparser2: 8.0.1 - parse5: 7.1.1 + parse5: 7.1.2 parse5-htmlparser2-tree-adapter: 7.0.0 dev: true @@ -4317,6 +4506,13 @@ packages: optionalDependencies: '@colors/colors': 1.5.0 + /cli-truncate/3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + /cliui/6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: @@ -4381,19 +4577,20 @@ packages: /commander/9.4.1: resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} engines: {node: ^12.20.0 || >=14} + dev: false /commondir/1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} dev: false - /compatfactory/1.0.1_typescript@4.9.4: + /compatfactory/1.0.1_typescript@5.0.2: resolution: {integrity: sha512-hR9u0HSZTKDNNchPtMHg6myeNx0XO+av7UZIJPsi4rPALJBHi/W5Mbwi19hC/xm6y3JkYpxVYjTqnSGsU5X/iw==} engines: {node: '>=14.9.0'} peerDependencies: typescript: '*' dependencies: helpertypes: 0.0.18 - typescript: 4.9.4 + typescript: 5.0.2 dev: false /concat-map/0.0.1: @@ -4436,11 +4633,6 @@ packages: browserslist: 4.21.4 dev: true - /core-js-pure/3.27.1: - resolution: {integrity: sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==} - requiresBuild: true - dev: true - /cosmiconfig/7.0.1: resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} engines: {node: '>=10'} @@ -4472,7 +4664,7 @@ packages: resolution: {integrity: sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA==} engines: {node: '>=14.9.0'} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.15.5 dev: false /css-color-keywords/1.0.0: @@ -4617,6 +4809,12 @@ packages: dependencies: cssom: 0.3.8 + /cssstyle/3.0.0: + resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} + engines: {node: '>=14'} + dependencies: + rrweb-cssom: 0.6.0 + /csstype/3.1.1: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: true @@ -4659,6 +4857,14 @@ packages: whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 + /data-urls/4.0.0: + resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} + engines: {node: '>=14'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -4668,6 +4874,7 @@ packages: optional: true dependencies: ms: 2.0.0 + dev: true /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} @@ -4719,22 +4926,26 @@ packages: /decimal.js/10.4.2: resolution: {integrity: sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==} + /decimal.js/10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + /deep-eql/4.1.2: resolution: {integrity: sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==} engines: {node: '>=6'} dependencies: type-detect: 4.0.8 - dev: true - /deep-equal/2.1.0: - resolution: {integrity: sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA==} + /deep-equal/2.2.0: + resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} dependencies: call-bind: 1.0.2 - es-get-iterator: 1.1.2 - get-intrinsic: 1.1.3 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.0 is-arguments: 1.1.1 + is-array-buffer: 3.0.2 is-date-object: 1.0.5 is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 isarray: 2.0.5 object-is: 1.1.5 object-keys: 1.1.1 @@ -4763,8 +4974,8 @@ packages: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} - /define-properties/1.1.4: - resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} + /define-properties/1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} engines: {node: '>= 0.4'} dependencies: has-property-descriptors: 1.0.0 @@ -4815,6 +5026,10 @@ packages: engines: {node: '>=8'} dev: true + /diff/5.1.0: + resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + engines: {node: '>=0.3.1'} + /dir-glob/3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4843,7 +5058,7 @@ packages: /dom-helpers/5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 csstype: 3.1.1 dev: true @@ -4932,10 +5147,6 @@ packages: ansi-colors: 4.1.3 dev: true - /ensure-posix-path/1.1.1: - resolution: {integrity: sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==} - dev: true - /entities/2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: false @@ -4957,19 +5168,19 @@ packages: es-to-primitive: 1.2.1 function-bind: 1.1.1 function.prototype.name: 1.1.5 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 get-symbol-description: 1.0.0 has: 1.0.3 has-property-descriptors: 1.0.0 has-symbols: 1.0.3 - internal-slot: 1.0.3 + internal-slot: 1.0.5 is-callable: 1.2.7 is-negative-zero: 2.0.2 is-regex: 1.1.4 is-shared-array-buffer: 1.0.2 is-string: 1.0.7 is-weakref: 1.0.2 - object-inspect: 1.12.2 + object-inspect: 1.12.3 object-keys: 1.1.1 object.assign: 4.1.4 regexp.prototype.flags: 1.4.3 @@ -4978,17 +5189,18 @@ packages: string.prototype.trimstart: 1.0.6 unbox-primitive: 1.0.2 - /es-get-iterator/1.1.2: - resolution: {integrity: sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==} + /es-get-iterator/1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 has-symbols: 1.0.3 is-arguments: 1.1.1 is-map: 2.0.2 is-set: 2.0.2 is-string: 1.0.7 isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 /es-module-lexer/0.10.5: resolution: {integrity: sha512-+7IwY/kiGAacQfY+YBhKMvEmyAJnw5grTUgjG85Pe7vcUI/6b7pZjZG8nQ7+48YhzEAEqrEgD2dCz/JIK+AYvw==} @@ -5217,34 +5429,34 @@ packages: esbuild-windows-arm64: 0.15.13 dev: true - /esbuild/0.16.13: - resolution: {integrity: sha512-oYwFdSEIoKM1oYzyem1osgKJAvg5447XF+05ava21fOtilyb2HeQQh26/74K4WeAk5dZmj/Mx10zUqUnI14jhA==} + /esbuild/0.17.12: + resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.16.13 - '@esbuild/android-arm64': 0.16.13 - '@esbuild/android-x64': 0.16.13 - '@esbuild/darwin-arm64': 0.16.13 - '@esbuild/darwin-x64': 0.16.13 - '@esbuild/freebsd-arm64': 0.16.13 - '@esbuild/freebsd-x64': 0.16.13 - '@esbuild/linux-arm': 0.16.13 - '@esbuild/linux-arm64': 0.16.13 - '@esbuild/linux-ia32': 0.16.13 - '@esbuild/linux-loong64': 0.16.13 - '@esbuild/linux-mips64el': 0.16.13 - '@esbuild/linux-ppc64': 0.16.13 - '@esbuild/linux-riscv64': 0.16.13 - '@esbuild/linux-s390x': 0.16.13 - '@esbuild/linux-x64': 0.16.13 - '@esbuild/netbsd-x64': 0.16.13 - '@esbuild/openbsd-x64': 0.16.13 - '@esbuild/sunos-x64': 0.16.13 - '@esbuild/win32-arm64': 0.16.13 - '@esbuild/win32-ia32': 0.16.13 - '@esbuild/win32-x64': 0.16.13 + '@esbuild/android-arm': 0.17.12 + '@esbuild/android-arm64': 0.17.12 + '@esbuild/android-x64': 0.17.12 + '@esbuild/darwin-arm64': 0.17.12 + '@esbuild/darwin-x64': 0.17.12 + '@esbuild/freebsd-arm64': 0.17.12 + '@esbuild/freebsd-x64': 0.17.12 + '@esbuild/linux-arm': 0.17.12 + '@esbuild/linux-arm64': 0.17.12 + '@esbuild/linux-ia32': 0.17.12 + '@esbuild/linux-loong64': 0.17.12 + '@esbuild/linux-mips64el': 0.17.12 + '@esbuild/linux-ppc64': 0.17.12 + '@esbuild/linux-riscv64': 0.17.12 + '@esbuild/linux-s390x': 0.17.12 + '@esbuild/linux-x64': 0.17.12 + '@esbuild/netbsd-x64': 0.17.12 + '@esbuild/openbsd-x64': 0.17.12 + '@esbuild/sunos-x64': 0.17.12 + '@esbuild/win32-arm64': 0.17.12 + '@esbuild/win32-ia32': 0.17.12 + '@esbuild/win32-x64': 0.17.12 /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -5270,7 +5482,7 @@ packages: optionalDependencies: source-map: 0.6.1 - /eslint-config-airbnb-base/15.0.0_ol7jqilc3wemtdbq3nzhywgxq4: + /eslint-config-airbnb-base/15.0.0_eakrjjutlgqjxe5ydhtnd4qdmy: resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -5278,14 +5490,14 @@ packages: eslint-plugin-import: ^2.25.2 dependencies: confusing-browser-globals: 1.0.11 - eslint: 8.31.0 - eslint-plugin-import: 2.26.0_cxu27kyieece4tnvunezm4whiq + eslint: 8.36.0 + eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq object.assign: 4.1.4 object.entries: 1.1.6 semver: 6.3.0 dev: true - /eslint-config-airbnb/19.0.4_kdrd7zxcgo7evu26hvr6zfy33i: + /eslint-config-airbnb/19.0.4_guhfqc3yvckhutqwrddiy54d5i: resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -5295,34 +5507,35 @@ packages: eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 dependencies: - eslint: 8.31.0 - eslint-config-airbnb-base: 15.0.0_ol7jqilc3wemtdbq3nzhywgxq4 - eslint-plugin-import: 2.26.0_cxu27kyieece4tnvunezm4whiq - eslint-plugin-jsx-a11y: 6.6.1_eslint@8.31.0 - eslint-plugin-react: 7.31.11_eslint@8.31.0 - eslint-plugin-react-hooks: 4.6.0_eslint@8.31.0 + eslint: 8.36.0 + eslint-config-airbnb-base: 15.0.0_eakrjjutlgqjxe5ydhtnd4qdmy + eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq + eslint-plugin-jsx-a11y: 6.7.1_eslint@8.36.0 + eslint-plugin-react: 7.32.2_eslint@8.36.0 + eslint-plugin-react-hooks: 4.6.0_eslint@8.36.0 object.assign: 4.1.4 object.entries: 1.1.6 dev: true - /eslint-config-prettier/8.6.0_eslint@8.31.0: - resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} + /eslint-config-prettier/8.8.0_eslint@8.36.0: + resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.31.0 + eslint: 8.36.0 - /eslint-import-resolver-node/0.3.6: - resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} + /eslint-import-resolver-node/0.3.7: + resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} dependencies: debug: 3.2.7 + is-core-module: 2.11.0 resolve: 1.22.1 transitivePeerDependencies: - supports-color - /eslint-import-resolver-typescript/3.5.2_ol7jqilc3wemtdbq3nzhywgxq4: - resolution: {integrity: sha512-zX4ebnnyXiykjhcBvKIf5TNvt8K7yX6bllTRZ14MiurKPjDpCAZujlszTdB8pcNXhZcOf+god4s9SjQa5GnytQ==} + /eslint-import-resolver-typescript/3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy: + resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -5330,8 +5543,8 @@ packages: dependencies: debug: 4.3.4 enhanced-resolve: 5.10.0 - eslint: 8.31.0 - eslint-plugin-import: 2.26.0_cxu27kyieece4tnvunezm4whiq + eslint: 8.36.0 + eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq get-tsconfig: 4.2.0 globby: 13.1.2 is-core-module: 2.11.0 @@ -5340,7 +5553,7 @@ packages: transitivePeerDependencies: - supports-color - /eslint-module-utils/2.7.4_gauu7rrsoohvlnqdwirscmegn4: + /eslint-module-utils/2.7.4_ab4tb467oik4rhsaavmctlutka: resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -5361,15 +5574,15 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu debug: 3.2.7 - eslint: 8.31.0 - eslint-import-resolver-node: 0.3.6 + eslint: 8.36.0 + eslint-import-resolver-node: 0.3.7 + eslint-import-resolver-typescript: 3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy transitivePeerDependencies: - supports-color - dev: false - /eslint-module-utils/2.7.4_zg4jn2jp3ute3go2jsvatsfmsa: + /eslint-module-utils/2.7.4_tf7h2azriypc3gaglz256o6pea: resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -5390,16 +5603,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu debug: 3.2.7 - eslint: 8.31.0 - eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 3.5.2_ol7jqilc3wemtdbq3nzhywgxq4 + eslint: 8.36.0 + eslint-import-resolver-node: 0.3.7 transitivePeerDependencies: - supports-color + dev: false - /eslint-plugin-import/2.26.0_cxu27kyieece4tnvunezm4whiq: - resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} + /eslint-plugin-import/2.27.5_as6wyplljmmarlclp2tx3tj6rq: + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -5408,28 +5621,30 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu array-includes: 3.1.6 array.prototype.flat: 1.3.1 - debug: 2.6.9 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.31.0 - eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.4_zg4jn2jp3ute3go2jsvatsfmsa + eslint: 8.36.0 + eslint-import-resolver-node: 0.3.7 + eslint-module-utils: 2.7.4_ab4tb467oik4rhsaavmctlutka has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 minimatch: 3.1.2 object.values: 1.1.6 resolve: 1.22.1 + semver: 6.3.0 tsconfig-paths: 3.14.1 transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - /eslint-plugin-import/2.26.0_m2kn7xiag5lymyarkgri27ztxm: - resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} + /eslint-plugin-import/2.27.5_cnkxirszkzb4o6ts7gbclno24e: + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -5438,20 +5653,22 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.48.0_iukboom6ndih5an6iafl45j2fe + '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu array-includes: 3.1.6 array.prototype.flat: 1.3.1 - debug: 2.6.9 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.31.0 - eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.4_gauu7rrsoohvlnqdwirscmegn4 + eslint: 8.36.0 + eslint-import-resolver-node: 0.3.7 + eslint-module-utils: 2.7.4_tf7h2azriypc3gaglz256o6pea has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 minimatch: 3.1.2 object.values: 1.1.6 resolve: 1.22.1 + semver: 6.3.0 tsconfig-paths: 3.14.1 transitivePeerDependencies: - eslint-import-resolver-typescript @@ -5467,40 +5684,43 @@ packages: vscode-json-languageservice: 4.2.1 dev: false - /eslint-plugin-jsonc/2.5.0_eslint@8.31.0: - resolution: {integrity: sha512-G257khwkrOQ5MJpSzz4yQh5K12W4xFZRcHmVlhVFWh2GCLDX+JwHnmkQoUoFDbOieSPBMsPFZDTJScwrXiWlIg==} + /eslint-plugin-jsonc/2.7.0_eslint@8.36.0: + resolution: {integrity: sha512-DZgC71h/hZ9t5k/OGAKOMdJCleg2neZLL7No+YYi2ZMroCN4X5huZdrLf1USbrc6UTHwYujd1EDwXHg1qJ6CYw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: - eslint: 8.31.0 - eslint-utils: 3.0.0_eslint@8.31.0 + '@eslint-community/eslint-utils': 4.3.0_eslint@8.36.0 + eslint: 8.36.0 jsonc-eslint-parser: 2.1.0 natural-compare: 1.4.0 - /eslint-plugin-jsx-a11y/6.6.1_eslint@8.31.0: - resolution: {integrity: sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==} + /eslint-plugin-jsx-a11y/6.7.1_eslint@8.36.0: + resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} engines: {node: '>=4.0'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 dependencies: - '@babel/runtime': 7.20.7 - aria-query: 4.2.2 + '@babel/runtime': 7.21.0 + aria-query: 5.1.3 array-includes: 3.1.6 + array.prototype.flatmap: 1.3.1 ast-types-flow: 0.0.7 - axe-core: 4.6.1 - axobject-query: 2.2.0 + axe-core: 4.6.3 + axobject-query: 3.1.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 8.31.0 + eslint: 8.36.0 has: 1.0.3 jsx-ast-utils: 3.3.3 - language-tags: 1.0.7 + language-tags: 1.0.5 minimatch: 3.1.2 + object.entries: 1.1.6 + object.fromentries: 2.0.6 semver: 6.3.0 dev: true - /eslint-plugin-prettier/4.2.1_32m5uc2milwdw3tnkcq5del26y: + /eslint-plugin-prettier/4.2.1_ose2zoovovx4ulolhifz3tfzx4: resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -5511,22 +5731,22 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.31.0 - eslint-config-prettier: 8.6.0_eslint@8.31.0 - prettier: 2.8.1 + eslint: 8.36.0 + eslint-config-prettier: 8.8.0_eslint@8.36.0 + prettier: 2.8.6 prettier-linter-helpers: 1.0.0 - /eslint-plugin-react-hooks/4.6.0_eslint@8.31.0: + /eslint-plugin-react-hooks/4.6.0_eslint@8.36.0: resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 dependencies: - eslint: 8.31.0 + eslint: 8.36.0 dev: true - /eslint-plugin-react/7.31.11_eslint@8.31.0: - resolution: {integrity: sha512-TTvq5JsT5v56wPa9OYHzsrOlHzKZKjV+aLgS+55NJP/cuzdiQPC7PfYoUjMoxlffKtvijpk7vA/jmuqRb9nohw==} + /eslint-plugin-react/7.32.2_eslint@8.36.0: + resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 @@ -5535,7 +5755,7 @@ packages: array.prototype.flatmap: 1.3.1 array.prototype.tosorted: 1.1.1 doctrine: 2.1.0 - eslint: 8.31.0 + eslint: 8.36.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.3 minimatch: 3.1.2 @@ -5549,14 +5769,14 @@ packages: string.prototype.matchall: 4.0.8 dev: true - /eslint-plugin-simple-import-sort/8.0.0_eslint@8.31.0: - resolution: {integrity: sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==} + /eslint-plugin-simple-import-sort/10.0.0_eslint@8.36.0: + resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} peerDependencies: eslint: '>=5.0.0' dependencies: - eslint: 8.31.0 + eslint: 8.36.0 - /eslint-plugin-unused-imports/2.0.0_eslint@8.31.0: + /eslint-plugin-unused-imports/2.0.0_eslint@8.36.0: resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -5566,11 +5786,11 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - eslint: 8.31.0 + eslint: 8.36.0 eslint-rule-composer: 0.3.0 dev: false - /eslint-plugin-unused-imports/2.0.0_zgazubnvp3urkgs5b7mw2pde3m: + /eslint-plugin-unused-imports/2.0.0_pjgbsoxltfjhart6hcjsvw66hu: resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -5580,8 +5800,8 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.48.0_k73wpmdolxikpyqun3p36akaaq - eslint: 8.31.0 + '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 + eslint: 8.36.0 eslint-rule-composer: 0.3.0 /eslint-rule-composer/0.3.0: @@ -5602,29 +5822,24 @@ packages: esrecurse: 4.3.0 estraverse: 5.3.0 - /eslint-utils/3.0.0_eslint@8.31.0: - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.31.0 - eslint-visitor-keys: 2.1.0 - /eslint-visitor-keys/2.1.0: resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} engines: {node: '>=10'} + dev: true /eslint-visitor-keys/3.3.0: resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /eslint/8.31.0: - resolution: {integrity: sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==} + /eslint/8.36.0: + resolution: {integrity: sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint/eslintrc': 1.4.1 + '@eslint-community/eslint-utils': 4.3.0_eslint@8.36.0 + '@eslint-community/regexpp': 4.4.0 + '@eslint/eslintrc': 2.0.1 + '@eslint/js': 8.36.0 '@humanwhocodes/config-array': 0.11.8 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -5635,10 +5850,9 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.31.0 eslint-visitor-keys: 3.3.0 - espree: 9.4.1 - esquery: 1.4.0 + espree: 9.5.0 + esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 @@ -5659,7 +5873,6 @@ packages: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.1 - regexpp: 3.2.0 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 text-table: 0.2.0 @@ -5680,14 +5893,23 @@ packages: acorn: 8.8.1 acorn-jsx: 5.3.2_acorn@8.8.1 eslint-visitor-keys: 3.3.0 + dev: false + + /espree/9.5.0: + resolution: {integrity: sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.2 + acorn-jsx: 5.3.2_acorn@8.8.2 + eslint-visitor-keys: 3.3.0 /esprima/4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - /esquery/1.4.0: - resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + /esquery/1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 @@ -5872,7 +6094,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 functions-have-names: 1.2.3 @@ -5896,10 +6118,9 @@ packages: /get-func-name/2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} - dev: true - /get-intrinsic/1.1.3: - resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + /get-intrinsic/1.2.0: + resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} dependencies: function-bind: 1.1.1 has: 1.0.3 @@ -5917,7 +6138,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 /get-tsconfig/4.2.0: resolution: {integrity: sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==} @@ -5995,7 +6216,7 @@ packages: /gopd/1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 /graceful-fs/4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} @@ -6003,11 +6224,12 @@ packages: /grapheme-splitter/1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - /happy-dom/8.1.1: - resolution: {integrity: sha512-uI8NneN2B0D+vwIhjQVKtIUYOSh/zymfj61bU/fxkoAw+Aktn0ewG6dYKyFPOvyBoFLPg3S8fsn2OqSoYCqJeQ==} + /happy-dom/8.9.0: + resolution: {integrity: sha512-JZwJuGdR7ko8L61136YzmrLv7LgTh5b8XaEM3P709mLjyQuXJ3zHTDXvUtBBahRjGlcYW0zGjIiEWizoTUGKfA==} dependencies: css.escape: 1.5.1 he: 1.2.0 + iconv-lite: 0.6.3 node-fetch: 2.6.7 webidl-conversions: 7.0.0 whatwg-encoding: 2.0.0 @@ -6035,7 +6257,7 @@ packages: /has-property-descriptors/1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 /has-symbols/1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} @@ -6158,6 +6380,7 @@ packages: engines: {node: '>=8'} dependencies: import-from: 3.0.0 + dev: false /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -6171,6 +6394,7 @@ packages: engines: {node: '>=8'} dependencies: resolve-from: 5.0.0 + dev: false /imurmurhash/0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -6194,11 +6418,11 @@ packages: resolution: {integrity: sha512-GOucsp9EcdlLdhPUyOTvQDnbFJtp2WBWZV1Jqe+mVnkJQBL3w96+fB84C+JL+EKXOspMdB0eMDQPDp5w9fkfZA==} dev: false - /internal-slot/1.0.3: - resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} + /internal-slot/1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 has: 1.0.3 side-channel: 1.0.4 @@ -6219,6 +6443,13 @@ packages: call-bind: 1.0.2 has-tostringtag: 1.0.0 + /is-array-buffer/3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + is-typed-array: 1.1.10 + /is-arrayish/0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -6283,6 +6514,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + /is-fullwidth-code-point/4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + /is-glob/4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -6384,7 +6619,7 @@ packages: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 /is-windows/1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} @@ -6467,6 +6702,46 @@ packages: - supports-color - utf-8-validate + /jsdom/21.1.1: + resolution: {integrity: sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.6 + acorn: 8.8.2 + acorn-globals: 7.0.1 + cssstyle: 3.0.0 + data-urls: 4.0.0 + decimal.js: 10.4.3 + domexception: 4.0.0 + escodegen: 2.0.0 + form-data: 4.0.0 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.2 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.2 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + ws: 8.13.0 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + /jsesc/0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -6502,14 +6777,21 @@ packages: resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} engines: {node: '>=6'} hasBin: true + dev: false + + /json5/2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true /jsonc-eslint-parser/2.1.0: resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 eslint-visitor-keys: 3.3.0 - espree: 9.4.1 + espree: 9.5.0 semver: 7.3.8 /jsonc-parser/3.2.0: @@ -6559,8 +6841,8 @@ packages: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: true - /language-tags/1.0.7: - resolution: {integrity: sha512-bSytju1/657hFjgUzPAPqszxH62ouE8nQFoFaVlIQfne4wO/wXC9A4+m8jYve7YBBvi59eq0SUpcshvG8h5Usw==} + /language-tags/1.0.5: + resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==} dependencies: language-subtag-registry: 0.3.22 dev: true @@ -6587,31 +6869,6 @@ packages: /lines-and-columns/1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - /lint-to-the-future-eslint/1.0.1_eslint@8.31.0: - resolution: {integrity: sha512-t8HLyM68VizdKmZbIm4CJkIHSKCgNzEdOZQi4bKRE97iAJ39jRHdfKlwrQgZqxxFxro12BZL+gC4iOGJdpOchA==} - engines: {node: 10.* || >= 12.*} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - eslint: 8.31.0 - import-cwd: 3.0.0 - semver: 7.3.8 - walk-sync: 3.0.0 - dev: true - - /lint-to-the-future/1.3.1: - resolution: {integrity: sha512-9rGftL2dPehLDc2D/kh+MU/Hsrq0JwqBJYwus/ovIVckRlQa9dX93J2jjwKuaukVuwVCLp8yvSWR2eRj+iMITg==} - engines: {node: 10.* || >= 12} - hasBin: true - dependencies: - commander: 9.4.1 - fs-extra: 7.0.1 - import-cwd: 3.0.0 - node-fetch: 2.6.7 - transitivePeerDependencies: - - encoding - dev: true - /load-yaml-file/0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'} @@ -6630,7 +6887,6 @@ packages: /local-pkg/0.4.2: resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} engines: {node: '>=14'} - dev: true /locate-path/5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} @@ -6681,7 +6937,6 @@ packages: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} dependencies: get-func-name: 2.0.0 - dev: true /lru-cache/4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -6705,6 +6960,12 @@ packages: /lz-string/1.4.4: resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} hasBin: true + dev: false + + /lz-string/1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + dev: true /magic-string/0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} @@ -6735,14 +6996,6 @@ packages: engines: {node: '>=8'} dev: true - /matcher-collection/2.0.1: - resolution: {integrity: sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==} - engines: {node: 6.* || 8.* || >= 10.*} - dependencies: - '@types/minimatch': 3.0.5 - minimatch: 3.1.2 - dev: true - /mdn-data/2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} dev: false @@ -6819,14 +7072,13 @@ packages: engines: {node: '>= 8.0.0'} dev: true - /mlly/1.0.0: - resolution: {integrity: sha512-QL108Hwt+u9bXdWgOI0dhzZfACovn5Aen4Xvc8Jasd9ouRH4NjnrXEiyP3nVvJo91zPlYjVRckta0Nt2zfoR6g==} + /mlly/1.2.0: + resolution: {integrity: sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==} dependencies: - acorn: 8.8.1 - pathe: 1.0.0 - pkg-types: 1.0.1 - ufo: 1.0.1 - dev: true + acorn: 8.8.2 + pathe: 1.1.0 + pkg-types: 1.0.2 + ufo: 1.1.1 /mrmime/1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} @@ -6835,6 +7087,7 @@ packages: /ms/2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -6921,15 +7174,15 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-inspect/1.12.2: - resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + /object-inspect/1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} /object-is/1.1.5: resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 /object-keys/1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -6945,7 +7198,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 has-symbols: 1.0.3 object-keys: 1.1.1 @@ -6954,7 +7207,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 dev: true @@ -6963,14 +7216,14 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 dev: true /object.hasown/1.1.2: resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} dependencies: - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 dev: true @@ -6979,7 +7232,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 /once/1.4.0: @@ -7051,6 +7304,12 @@ packages: dependencies: yocto-queue: 0.1.0 + /p-limit/4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + /p-locate/4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -7108,7 +7367,7 @@ packages: resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} dependencies: domhandler: 5.0.3 - parse5: 7.1.1 + parse5: 7.1.2 dev: true /parse5/7.1.1: @@ -7116,6 +7375,11 @@ packages: dependencies: entities: 4.4.0 + /parse5/7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + /path-exists/4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -7135,17 +7399,11 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - /pathe/0.2.0: - resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} - dev: true - - /pathe/1.0.0: - resolution: {integrity: sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==} - dev: true + /pathe/1.1.0: + resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} /pathval/1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -7171,13 +7429,12 @@ packages: find-up: 4.1.0 dev: true - /pkg-types/1.0.1: - resolution: {integrity: sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==} + /pkg-types/1.0.2: + resolution: {integrity: sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==} dependencies: jsonc-parser: 3.2.0 - mlly: 1.0.0 - pathe: 1.0.0 - dev: true + mlly: 1.2.0 + pathe: 1.1.0 /please-upgrade-node/3.2.0: resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} @@ -7559,6 +7816,15 @@ packages: nanoid: 3.3.4 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: false + + /postcss/8.4.21: + resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 /preact-render-to-string/5.2.6_preact@10.11.3: resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} @@ -7600,6 +7866,12 @@ packages: resolution: {integrity: sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==} engines: {node: '>=10.13.0'} hasBin: true + dev: false + + /prettier/2.8.6: + resolution: {integrity: sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==} + engines: {node: '>=10.13.0'} + hasBin: true /pretty-format/27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} @@ -7643,6 +7915,10 @@ packages: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} + /punycode/2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + /purecss/3.0.0: resolution: {integrity: sha512-IdYbGwbmuA7Hy9ACIO1q7ks4xGLcJSVHxJT2BXIz2c4Ve1aSrNU5bAzA1ILT4Gmdy5K59ruWoRPf9WvJZU5fbA==} dev: false @@ -7685,7 +7961,7 @@ packages: peerDependencies: react: '*' dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 react: 18.2.0 dev: false @@ -7721,7 +7997,7 @@ packages: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -7802,7 +8078,7 @@ packages: /regenerator-transform/0.15.0: resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 dev: true /regexp.prototype.flags/1.4.3: @@ -7810,13 +8086,9 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 functions-have-names: 1.2.3 - /regexpp/3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - /regexpu-core/5.2.1: resolution: {integrity: sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==} engines: {node: '>=4'} @@ -7923,7 +8195,7 @@ packages: - ts-node dev: false - /rollup-plugin-ts/3.0.2_esmavzhadgk2idmxtiodxm33ma: + /rollup-plugin-ts/3.0.2_tumybvdr6br7dr3yffpdihdhou: resolution: {integrity: sha512-67qi2QTHewhLyKDG6fX3jpohWpmUPPIT/xJ7rsYK46X6MqmoWy64Ti0y8ygPfLv8mXDCdRZUofM3mTxDfCswRA==} engines: {node: '>=14.9.0', npm: '>=7.0.0', pnpm: '>=3.2.0', yarn: '>=1.13'} peerDependencies: @@ -7957,13 +8229,13 @@ packages: ansi-colors: 4.1.3 browserslist: 4.21.4 browserslist-generator: 1.0.66 - compatfactory: 1.0.1_typescript@4.9.4 + compatfactory: 1.0.1_typescript@5.0.2 crosspath: 2.0.0 magic-string: 0.26.7 rollup: 3.9.1 - ts-clone-node: 1.0.0_typescript@4.9.4 - tslib: 2.4.1 - typescript: 4.9.4 + ts-clone-node: 1.0.0_typescript@5.0.2 + tslib: 2.5.0 + typescript: 5.0.2 dev: false /rollup-pluginutils/2.8.2: @@ -7979,6 +8251,9 @@ packages: optionalDependencies: fsevents: 2.3.2 + /rrweb-cssom/0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -7987,7 +8262,7 @@ packages: /rxjs/7.5.7: resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} dependencies: - tslib: 2.4.1 + tslib: 2.5.0 dev: true /safe-identifier/0.4.2: @@ -7998,7 +8273,7 @@ packages: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 is-regex: 1.1.4 /safer-buffer/2.1.2: @@ -8045,7 +8320,6 @@ packages: /semver/6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - dev: true /semver/7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} @@ -8110,8 +8384,11 @@ packages: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 - object-inspect: 1.12.2 + get-intrinsic: 1.2.0 + object-inspect: 1.12.3 + + /siginfo/2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} /signal-exit/3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -8134,6 +8411,13 @@ packages: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} + /slice-ansi/5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + /smartwrap/2.0.2: resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} engines: {node: '>=6'} @@ -8208,6 +8492,9 @@ packages: deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' dev: false + /stackback/0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + /stacktracey/2.1.8: resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} dependencies: @@ -8215,6 +8502,15 @@ packages: get-source: 2.0.12 dev: false + /std-env/3.3.2: + resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} + + /stop-iteration-iterator/1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.5 + /stream-buffers/0.2.6: resolution: {integrity: sha512-ZRpmWyuCdg0TtNKk8bEqvm13oQvXMmzXDsfD4cBgcx5LouborvU5pm3JMkdTP3HcszyUI08AM1dHMXA5r2g6Sg==} engines: {node: '>= 0.3.0'} @@ -8250,11 +8546,11 @@ packages: resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 has-symbols: 1.0.3 - internal-slot: 1.0.3 + internal-slot: 1.0.5 regexp.prototype.flags: 1.4.3 side-channel: 1.0.4 dev: true @@ -8263,14 +8559,14 @@ packages: resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 /string.prototype.trimstart/1.0.6: resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 /strip-ansi/6.0.1: @@ -8304,7 +8600,6 @@ packages: resolution: {integrity: sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==} dependencies: acorn: 8.8.1 - dev: true /style-inject/0.3.0: resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} @@ -8383,7 +8678,7 @@ packages: engines: {node: ^14.18.0 || >=16.0.0} dependencies: '@pkgr/utils': 2.3.1 - tslib: 2.4.1 + tslib: 2.5.0 /tapable/2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} @@ -8409,17 +8704,14 @@ packages: /tinybench/2.3.1: resolution: {integrity: sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==} - dev: true - /tinypool/0.3.0: - resolution: {integrity: sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==} + /tinypool/0.4.0: + resolution: {integrity: sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA==} engines: {node: '>=14.0.0'} - dev: true /tinyspy/1.0.2: resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==} engines: {node: '>=14.0.0'} - dev: true /tmp/0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} @@ -8460,21 +8752,27 @@ packages: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} dependencies: - punycode: 2.1.1 + punycode: 2.3.0 + + /tr46/4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + dependencies: + punycode: 2.3.0 /trim-newlines/3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} dev: true - /ts-clone-node/1.0.0_typescript@4.9.4: + /ts-clone-node/1.0.0_typescript@5.0.2: resolution: {integrity: sha512-/cDYbr2HAXxFNeTT41c/xs/2bhLJjqnYheHsmA3AoHSt+n4JA4t0FL9Lk5O8kWnJ6jeB3kPcUoXIFtwERNzv6Q==} engines: {node: '>=14.9.0'} peerDependencies: typescript: '*' dependencies: - compatfactory: 1.0.1_typescript@4.9.4 - typescript: 4.9.4 + compatfactory: 1.0.1_typescript@5.0.2 + typescript: 5.0.2 dev: false /tsconfig-paths/3.14.1: @@ -8488,17 +8786,17 @@ packages: /tslib/1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - /tslib/2.4.1: - resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + /tslib/2.5.0: + resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - /tsutils/3.21.0_typescript@4.9.4: + /tsutils/3.21.0_typescript@5.0.2: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '*' dependencies: tslib: 1.14.1 - typescript: 4.9.4 + typescript: 5.0.2 /tsx/3.11.0: resolution: {integrity: sha512-q+q4xxu41+AafVwvAGqtNJ1ekPFd33ZhTMXvgIpHMqv/W89efwDRE9IyjhEAZm5iTHsshKaf1BYWSk789BrNCA==} @@ -8540,7 +8838,6 @@ packages: /type-detect/4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - dev: true /type-fest/0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} @@ -8561,9 +8858,9 @@ packages: engines: {node: '>=8'} dev: true - /typescript/4.9.4: - resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} - engines: {node: '>=4.2.0'} + /typescript/5.0.2: + resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==} + engines: {node: '>=12.20'} hasBin: true /ua-parser-js/1.0.32: @@ -8574,9 +8871,8 @@ packages: resolution: {integrity: sha512-pGtPAQmLwh+R9w81WVHzui1FfedpQWQpiaIIfPCwhtsBez4q6DYbJFfyXPVHPUTNFnedAvNEnkoFiLuhXIR94w==} dev: true - /ufo/1.0.1: - resolution: {integrity: sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==} - dev: true + /ufo/1.1.1: + resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} /unbox-primitive/1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -8636,7 +8932,7 @@ packages: /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: - punycode: 2.1.1 + punycode: 2.3.0 /url-parse/1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -8655,17 +8951,17 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite-node/0.26.3_@types+node@18.11.18: - resolution: {integrity: sha512-Te2bq0Bfvq6XiO718I+1EinMjpNYKws6SNHKOmVbILAQimKoZKDd+IZLlkaYcBXPpK3HFe2U80k8Zw+m3w/a2w==} + /vite-node/0.29.7_@types+node@18.15.5: + resolution: {integrity: sha512-PakCZLvz37yFfUPWBnLa1OYHPCGm5v4pmRrTcFN4V/N/T3I6tyP3z07S//9w+DdeL7vVd0VSeyMZuAh+449ZWw==} engines: {node: '>=v14.16.0'} hasBin: true dependencies: + cac: 6.7.14 debug: 4.3.4 - mlly: 1.0.0 - pathe: 0.2.0 - source-map: 0.6.1 - source-map-support: 0.5.21 - vite: 4.0.4_@types+node@18.11.18 + mlly: 1.2.0 + pathe: 1.1.0 + picocolors: 1.0.0 + vite: 4.2.1_@types+node@18.15.5 transitivePeerDependencies: - '@types/node' - less @@ -8674,15 +8970,14 @@ packages: - sugarss - supports-color - terser - dev: true - /vite-plugin-fonts/0.7.0_vite@4.0.4: + /vite-plugin-fonts/0.7.0_vite@4.2.1: resolution: {integrity: sha512-fisKirkQrA2RFwcyI96SENLu1FyRYNIiC/l5DGdD8oV3OsAWGrYKs0e7/VZF6l0rm0QiYA2sOVTzYfrLAzP9cw==} peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 dependencies: fast-glob: 3.2.12 - vite: 4.0.4 + vite: 4.2.1 /vite-plugin-mpa/1.1.4: resolution: {integrity: sha512-sLXMOdMl8t9B9/sxXXZ9CLt8QudhGSSKCX+bZ/ePaO7kp4SdoA5d6CV+EnCyNuQCenAbXKJzk3nM8Do0RgmSpA==} @@ -8692,8 +8987,8 @@ packages: yargs: 16.2.0 dev: true - /vite/4.0.4: - resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==} + /vite/4.2.1: + resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -8717,15 +9012,15 @@ packages: terser: optional: true dependencies: - esbuild: 0.16.13 - postcss: 8.4.20 + esbuild: 0.17.12 + postcss: 8.4.21 resolve: 1.22.1 rollup: 3.9.1 optionalDependencies: fsevents: 2.3.2 - /vite/4.0.4_@types+node@18.11.18: - resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==} + /vite/4.2.1_@types+node@18.15.5: + resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -8749,16 +9044,16 @@ packages: terser: optional: true dependencies: - '@types/node': 18.11.18 - esbuild: 0.16.13 - postcss: 8.4.20 + '@types/node': 18.15.5 + esbuild: 0.17.12 + postcss: 8.4.21 resolve: 1.22.1 rollup: 3.9.1 optionalDependencies: fsevents: 2.3.2 - /vitest/0.26.3_@vitest+ui@0.26.3: - resolution: {integrity: sha512-FmHxU9aUCxTi23keF3vxb/Qp0lYXaaJ+jRLGOUmMS3qVTOJvgGE+f1VArupA6pEhaG2Ans4X+zV9dqM5WISMbg==} + /vitest/0.29.7_@vitest+ui@0.29.7: + resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true peerDependencies: @@ -8767,6 +9062,8 @@ packages: '@vitest/ui': '*' happy-dom: '*' jsdom: '*' + safaridriver: '*' + webdriverio: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -8778,23 +9075,36 @@ packages: optional: true jsdom: optional: true + safaridriver: + optional: true + webdriverio: + optional: true dependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 - '@types/node': 18.11.18 - '@vitest/ui': 0.26.3 - acorn: 8.8.1 + '@types/node': 18.15.5 + '@vitest/expect': 0.29.7 + '@vitest/runner': 0.29.7 + '@vitest/spy': 0.29.7 + '@vitest/ui': 0.29.7 + '@vitest/utils': 0.29.7 + acorn: 8.8.2 acorn-walk: 8.2.0 + cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 local-pkg: 0.4.2 + pathe: 1.1.0 + picocolors: 1.0.0 source-map: 0.6.1 + std-env: 3.3.2 strip-literal: 1.0.0 tinybench: 2.3.1 - tinypool: 0.3.0 + tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.0.4_@types+node@18.11.18 - vite-node: 0.26.3_@types+node@18.11.18 + vite: 4.2.1_@types+node@18.15.5 + vite-node: 0.29.7_@types+node@18.15.5 + why-is-node-running: 2.2.2 transitivePeerDependencies: - less - sass @@ -8804,8 +9114,8 @@ packages: - terser dev: true - /vitest/0.26.3_giuftcgfn5z4uy6bdlohvyimia: - resolution: {integrity: sha512-FmHxU9aUCxTi23keF3vxb/Qp0lYXaaJ+jRLGOUmMS3qVTOJvgGE+f1VArupA6pEhaG2Ans4X+zV9dqM5WISMbg==} + /vitest/0.29.7_bi73zdcwqjrbwiah6tn5sspwie: + resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true peerDependencies: @@ -8814,6 +9124,8 @@ packages: '@vitest/ui': '*' happy-dom: '*' jsdom: '*' + safaridriver: '*' + webdriverio: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -8825,25 +9137,38 @@ packages: optional: true jsdom: optional: true + safaridriver: + optional: true + webdriverio: + optional: true dependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 - '@types/node': 18.11.18 - '@vitest/ui': 0.26.3 + '@types/node': 18.15.5 + '@vitest/expect': 0.29.7 + '@vitest/runner': 0.29.7 + '@vitest/spy': 0.29.7 + '@vitest/ui': 0.29.7 + '@vitest/utils': 0.29.7 acorn: 8.8.1 acorn-walk: 8.2.0 + cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 - happy-dom: 8.1.1 - jsdom: 20.0.3 + happy-dom: 8.9.0 + jsdom: 21.1.1 local-pkg: 0.4.2 + pathe: 1.1.0 + picocolors: 1.0.0 source-map: 0.6.1 + std-env: 3.3.2 strip-literal: 1.0.0 tinybench: 2.3.1 - tinypool: 0.3.0 + tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.0.4_@types+node@18.11.18 - vite-node: 0.26.3_@types+node@18.11.18 + vite: 4.2.1_@types+node@18.15.5 + vite-node: 0.29.7_@types+node@18.15.5 + why-is-node-running: 2.2.2 transitivePeerDependencies: - less - sass @@ -8853,6 +9178,68 @@ packages: - terser dev: true + /vitest/0.29.7_jsdom@21.1.1: + resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} + engines: {node: '>=v14.16.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + safaridriver: '*' + webdriverio: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@types/chai': 4.3.4 + '@types/chai-subset': 1.3.3 + '@types/node': 18.15.5 + '@vitest/expect': 0.29.7 + '@vitest/runner': 0.29.7 + '@vitest/spy': 0.29.7 + '@vitest/utils': 0.29.7 + acorn: 8.8.2 + acorn-walk: 8.2.0 + cac: 6.7.14 + chai: 4.3.7 + debug: 4.3.4 + jsdom: 21.1.1 + local-pkg: 0.4.2 + pathe: 1.1.0 + picocolors: 1.0.0 + source-map: 0.6.1 + std-env: 3.3.2 + strip-literal: 1.0.0 + tinybench: 2.3.1 + tinypool: 0.4.0 + tinyspy: 1.0.2 + vite: 4.2.1_@types+node@18.15.5 + vite-node: 0.29.7_@types+node@18.15.5 + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: false + /vscode-json-languageservice/4.2.1: resolution: {integrity: sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==} dependencies: @@ -8885,16 +9272,6 @@ packages: dependencies: xml-name-validator: 4.0.0 - /walk-sync/3.0.0: - resolution: {integrity: sha512-41TvKmDGVpm2iuH7o+DAOt06yyu/cSHpX3uzAwetzASvlNtVddgIjXIb2DfB/Wa20B1Jo86+1Dv1CraSU7hWdw==} - engines: {node: 10.* || >= 12.*} - dependencies: - '@types/minimatch': 3.0.5 - ensure-posix-path: 1.1.1 - matcher-collection: 2.0.1 - minimatch: 3.1.2 - dev: true - /wcwidth/1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: @@ -8926,6 +9303,13 @@ packages: tr46: 3.0.0 webidl-conversions: 7.0.0 + /whatwg-url/12.0.1: + resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==} + engines: {node: '>=14'} + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + /whatwg-url/5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: @@ -8987,6 +9371,14 @@ packages: dependencies: isexe: 2.0.0 + /why-is-node-running/2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + /word-wrap/1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} @@ -9031,6 +9423,18 @@ packages: utf-8-validate: optional: true + /ws/8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + /xml-name-validator/4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -9124,3 +9528,7 @@ packages: /yocto-queue/0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + + /yocto-queue/1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} diff --git a/workspace/build/package.json b/workspace/build/package.json index 2ef4694b..7d8022b2 100644 --- a/workspace/build/package.json +++ b/workspace/build/package.json @@ -35,13 +35,13 @@ "@types/rollup__plugin-commonjs": "workspace:^", "@types/rollup__plugin-node-resolve": "workspace:^", "@types/rollup-plugin-polyfill-node": "workspace:*", - "@typescript-eslint/parser": "^5.42.0", + "@typescript-eslint/parser": "^5.56.0", "eslint": "*", - "eslint-config-prettier": "^8.6.0", - "eslint-plugin-import": "^2.26.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", "eslint-plugin-json": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-simple-import-sort": "^8.0.0", + "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^2.0.0", "magic-string": "^0.27.0", "postcss": "^8.4.20", diff --git a/workspace/eslint/package.json b/workspace/eslint/package.json index d5d1fd57..cb0a5674 100644 --- a/workspace/eslint/package.json +++ b/workspace/eslint/package.json @@ -27,23 +27,23 @@ "test:types": "tsc -b" }, "dependencies": { - "@types/eslint": "^8.4.9", - "eslint-config-prettier": "^8.6.0", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", + "@types/eslint": "^8.21.3", + "eslint-config-prettier": "^8.8.0", + "eslint-import-resolver-typescript": "^3.5.3", + "eslint-plugin-import": "^2.27.5", "eslint-plugin-json": "^3.1.0", - "eslint-plugin-jsonc": "^2.5.0", + "eslint-plugin-jsonc": "^2.7.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-simple-import-sort": "^8.0.0", + "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^2.0.0", - "prettier": "^2.8.1" + "prettier": "^2.8.6" }, "devDependencies": { - "@types/node": "^18.11.9" + "@types/node": "^18.15.5" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.42.2-alpha", - "@typescript-eslint/parser": "^5.42.2-alpha", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.26.0", "jsonc-eslint-parser": "^2.1.0", "typescript": "*" diff --git a/workspace/eslint/src/base.js b/workspace/eslint/src/base.js index c23f1c27..66c5d911 100644 --- a/workspace/eslint/src/base.js +++ b/workspace/eslint/src/base.js @@ -1,5 +1,6 @@ -// eslint-disable-next-line unused-imports/no-unused-vars +// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unsafe-call const { Linter, ESLint } = require("eslint"); +// eslint-disable-next-line @typescript-eslint/no-unsafe-call const Rules = require("./rules.js"); /** @type {ESLint.ConfigData} */ @@ -7,7 +8,6 @@ exports.config = { parser: "@typescript-eslint/parser", parserOptions: { EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true, - warnOnUnsupportedTypeScriptVersion: false, ecmaVersion: "latest", }, settings: { diff --git a/workspace/eslint/src/esm.js b/workspace/eslint/src/esm.js index e77627da..d262ec0b 100644 --- a/workspace/eslint/src/esm.js +++ b/workspace/eslint/src/esm.js @@ -1,5 +1,6 @@ -// eslint-disable-next-line unused-imports/no-unused-vars +// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unsafe-call const { Linter, ESLint } = require("eslint"); +// eslint-disable-next-line @typescript-eslint/no-unsafe-call const Rules = require("./rules.js"); /** @type {ESLint.ConfigData} */ @@ -7,7 +8,6 @@ exports.config = { parser: "@typescript-eslint/parser", parserOptions: { EXPERIMENTAL_useSourceOfProjectReferenceRedirect: false, - warnOnUnsupportedTypeScriptVersion: false, ecmaVersion: "latest", }, settings: { diff --git a/workspace/eslint/tsconfig.json b/workspace/eslint/tsconfig.json index 69df831b..c7195f69 100644 --- a/workspace/eslint/tsconfig.json +++ b/workspace/eslint/tsconfig.json @@ -18,7 +18,6 @@ "experimentalDecorators": true, - "isolatedModules": true, "module": "CommonJS", "moduleResolution": "Node", "noPropertyAccessFromIndexSignature": true, @@ -32,7 +31,7 @@ "strict": true, - "types": ["vite/client", "../../packages/env", "node"], + "types": ["../../packages/env"], "useDefineForClassFields": true }, From 9fc23ba255bea1119ec3ba1e3aace56d36cba2ef Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 23 Mar 2023 11:36:00 -0700 Subject: [PATCH 02/46] Rename "internal" concepts to Tag and Tagged --- .vscode/settings.json | 2 - packages/react/react/src/debug/warnings.ts | 4 +- packages/react/react/src/element.ts | 6 +- .../universal/debug/src/component/stack.ts | 10 +- packages/universal/debug/src/timeline.ts | 54 +++--- packages/universal/interfaces/index.d.ts | 13 +- .../interfaces/src/debug-protocol/tree.d.ts | 8 +- .../universal/interfaces/src/description.d.ts | 2 +- packages/universal/interfaces/src/frame.d.ts | 4 +- .../universal/interfaces/src/protocol.d.ts | 33 ++-- packages/universal/js/src/collection.ts | 4 +- packages/universal/modifier/src/modifier.ts | 8 +- packages/universal/shared/index.ts | 2 +- packages/universal/shared/src/constants.ts | 10 +- .../universal/shared/tests/constants.spec.ts | 4 +- packages/universal/timeline/index.ts | 6 +- .../universal/timeline/src/timeline/frame.ts | 52 +++-- .../universal/timeline/src/timeline/frames.ts | 22 +-- .../timeline/src/timeline/protocol.ts | 179 +++++++----------- .../timeline/src/timeline/subscriptions.ts | 54 +++--- .../timeline/src/timeline/timeline.ts | 31 ++- .../universal/timeline/tests/pollable.spec.ts | 8 +- .../universal/timeline/tests/protocol.spec.ts | 75 +++----- .../timeline/tests/support/mini-reactives.ts | 26 +-- packages/universal/universal/index.ts | 2 +- .../universal/src/reactive-core/cell.ts | 6 +- .../universal/src/reactive-core/delegate.ts | 20 +- .../src/reactive-core/formula/formula.ts | 10 +- .../reactive-core/formula/polled-formula.ts | 10 +- .../universal/src/reactive-core/marker.ts | 8 +- .../universal/src/reactive-core/reactive.ts | 4 +- .../universal/src/reactive-core/static.ts | 4 +- .../universal/src/reactive-core/variants.ts | 20 +- packages/universal/universal/src/storage.ts | 18 +- .../universal/universal/tests/factory.spec.ts | 4 +- .../universal/universal/tests/setup.spec.ts | 22 +-- .../universal/tests/variants.spec.ts | 6 +- 37 files changed, 338 insertions(+), 413 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 58734b2f..14bd9e8a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -75,8 +75,6 @@ "pnpm-lock.yaml": true }, - "testing.automaticallyOpenPeekView": "never", - "typescript.preferences.importModuleSpecifier": "project-relative", "typescript.preferences.importModuleSpecifierEnding": "auto", "typescript.tsdk": "node_modules/typescript/lib", diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index 8d219558..546e3083 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,5 +1,5 @@ import { Message } from "@starbeam/debug"; -import { SubscriptionTarget, TIMELINE } from "@starbeam/timeline"; +import { Tagged, TIMELINE } from "@starbeam/timeline"; import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; @@ -10,7 +10,7 @@ if (import.meta.env.DEV) { if (!WARNED) { WARNED = true; - const description = SubscriptionTarget.description(reactive).userFacing; + const description = Tagged.description(reactive).userFacing; const caller = stack.caller; const pad = Math.max( diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index c373d1ee..fcd268b8 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,7 +1,7 @@ import type { browser } from "@domtree/flavors"; import { type DebugListener, Desc, type Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; -import type { SubscriptionTarget } from "@starbeam/timeline"; +import type { Tagged } from "@starbeam/timeline"; import { type CleanupTarget, LIFETIME, @@ -128,7 +128,7 @@ class Refs { export type DebugLifecycle = ( listener: DebugListener, - reactive: SubscriptionTarget + reactive: Tagged ) => () => void; /** @@ -203,7 +203,7 @@ export class ReactiveElement implements CleanupTarget { static subscribe( element: ReactiveElement, - reactive: SubscriptionTarget + reactive: Tagged ): void { const subscription = TIMELINE.on.change(reactive, element.notify); element.on.cleanup(subscription); diff --git a/packages/universal/debug/src/component/stack.ts b/packages/universal/debug/src/component/stack.ts index ba50d844..770bd58d 100644 --- a/packages/universal/debug/src/component/stack.ts +++ b/packages/universal/debug/src/component/stack.ts @@ -22,17 +22,17 @@ export interface Component { lifecycle: (timing: "layout" | "idle") => Lifecycle; ref: (description: interfaces.Description) => Ref; modifier: (timing: "layout" | "idle") => Modifier; - resource: (reactive: interfaces.SubscriptionTarget) => interfaces.Unsubscribe; + resource: (reactive: interfaces.Tagged) => interfaces.Unsubscribe; domResource: ( timing: "layout" | "idle", - reactive: interfaces.SubscriptionTarget + reactive: interfaces.Tagged ) => interfaces.Unsubscribe; } export interface Lifecycle { setup: ( timing: "layout" | "idle", - protocol: interfaces.SubscriptionTarget + protocol: interfaces.Tagged ) => interfaces.Unsubscribe; } @@ -108,7 +108,7 @@ if (import.meta.env.DEV) { } domResource( _timing: "layout" | "idle", - _reactive: interfaces.SubscriptionTarget + _reactive: interfaces.Tagged ): interfaces.Unsubscribe { throw new Error("Method not implemented."); } @@ -121,7 +121,7 @@ if (import.meta.env.DEV) { ref(_description: interfaces.Description): Ref { throw new Error("Method not implemented."); } - resource(_reactive: interfaces.SubscriptionTarget): interfaces.Unsubscribe { + resource(_reactive: interfaces.Tagged): interfaces.Unsubscribe { throw new Error("Method not implemented."); } } diff --git a/packages/universal/debug/src/timeline.ts b/packages/universal/debug/src/timeline.ts index 86627bc4..56e402b9 100644 --- a/packages/universal/debug/src/timeline.ts +++ b/packages/universal/debug/src/timeline.ts @@ -1,25 +1,25 @@ import type { - CellCore, + CellTag, Diff, - FormulaCore, + FormulaTag, Frame, - ReactiveCore, Stack, - SubscriptionTarget, + Tagged, + Tag, Timestamp, } from "@starbeam/interfaces"; -import { REACTIVE } from "@starbeam/shared"; +import { TAG } from "@starbeam/shared"; import { exhaustive } from "@starbeam/verify"; interface SubscriptionTargetStatics { - dependencies: (reactive: SubscriptionTarget) => Iterable; + dependencies: (reactive: Tagged) => Iterable; } -function reactiveInternals(reactive: SubscriptionTarget): ReactiveCore { - return reactive[REACTIVE]; +function reactiveInternals(reactive: Tagged): Tag { + return reactive[TAG]; } -interface OperationInfo { +interface OperationInfo { readonly at: Timestamp; readonly for: I; readonly caller: Stack; @@ -30,7 +30,7 @@ export type DebugOperationOptions = | CellUpdateOperation | FrameConsumeOperation; -export class LeafOperation { +export class LeafOperation { #data: OperationInfo; constructor(data: OperationInfo) { @@ -50,21 +50,21 @@ export class LeafOperation { } } -export class CellConsumeOperation extends LeafOperation { +export class CellConsumeOperation extends LeafOperation { readonly type = "cell:consume"; } -export class CellUpdateOperation extends LeafOperation { +export class CellUpdateOperation extends LeafOperation { readonly type = "cell:update"; } -interface FrameConsumeInfo extends OperationInfo { - readonly diff: Diff; +interface FrameConsumeInfo extends OperationInfo { + readonly diff: Diff; readonly frame: Frame; } -export class FrameConsumeOperation extends LeafOperation { - readonly #diff: Diff; +export class FrameConsumeOperation extends LeafOperation { + readonly #diff: Diff; readonly #frame: Frame; readonly type = "frame:consume"; @@ -74,7 +74,7 @@ export class FrameConsumeOperation extends LeafOperation { this.#frame = data.frame; } - get diff(): Diff { + get diff(): Diff { return this.#diff; } @@ -86,7 +86,7 @@ export class MutationLog { readonly type = "mutation"; // This makes `DebugOperation.for` ==== `ReactiveInternals | undefined`, which makes it possible // to easily compare the `for` value without a lot of extra type shenanigans. - readonly for: ReactiveCore | undefined = undefined; + readonly for: Tag | undefined = undefined; readonly #at: Timestamp; #description: string; @@ -116,13 +116,13 @@ export type DebugOperation = export interface Flush { readonly history: DebugOperation[]; - for: (reactive: SubscriptionTarget) => readonly DebugOperation[]; + for: (reactive: Tagged) => readonly DebugOperation[]; } export type DebugListener = InstanceType; export type DebugFilter = - | { type: "by-reactive"; reactive: SubscriptionTarget } + | { type: "by-reactive"; reactive: Tagged } | { type: "all" } | { type: "none" }; @@ -170,7 +170,7 @@ export class DebugTimeline { static Flush = class Flush { constructor(readonly history: DebugOperation[]) {} - for(reactive: SubscriptionTarget): DebugOperation[] { + for(reactive: Tagged): DebugOperation[] { const internals = reactiveInternals(reactive); return this.history.filter((item) => item.for === internals); } @@ -296,7 +296,7 @@ export class DebugTimeline { } } - #consumeCell(cell: CellCore, caller: Stack): void { + #consumeCell(cell: CellTag, caller: Stack): void { this.#add( new CellConsumeOperation({ at: this.#timestamp.now(), @@ -306,15 +306,15 @@ export class DebugTimeline { ); } - consumeCell(internals: CellCore, caller: Stack): void { + consumeCell(internals: CellTag, caller: Stack): void { this.#consumeCell(internals, caller); } - consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { + consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { this.#consumeFrame(frame, diff, caller); } - updateCell(cell: CellCore, caller: Stack): void { + updateCell(cell: CellTag, caller: Stack): void { this.#add( new CellUpdateOperation({ at: this.#timestamp.now(), @@ -324,11 +324,11 @@ export class DebugTimeline { ); } - #consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { + #consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { this.#add( new FrameConsumeOperation({ at: this.#timestamp.now(), - for: frame[REACTIVE], + for: frame[TAG], diff, caller, frame, diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index daa4b9fa..3b8c5962 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -25,16 +25,17 @@ export type { ValidFrame, } from "./src/frame.js"; export type { - CellCore, - DelegateCore, - FormulaCore, + CellTag, + DelegateTag, + FormulaTag, Reactive, ReactiveCell, - ReactiveCore, ReactiveId, ReactiveValue, - StaticCore, - SubscriptionTarget, + StaticTag, + Tag, + Tagged, + TagType, } from "./src/protocol.js"; export type { DisplayParts, diff --git a/packages/universal/interfaces/src/debug-protocol/tree.d.ts b/packages/universal/interfaces/src/debug-protocol/tree.d.ts index 87a5796d..da0475a5 100644 --- a/packages/universal/interfaces/src/debug-protocol/tree.d.ts +++ b/packages/universal/interfaces/src/debug-protocol/tree.d.ts @@ -1,7 +1,7 @@ import type * as anydom from "@domtree/any"; import type { Description } from "../description.js"; -import type { SubscriptionTarget } from "../protocol.js"; +import type { Tagged } from "../protocol.js"; export interface INode { readonly type: string; @@ -52,7 +52,7 @@ export interface ComponentNode extends INode { export interface LifecyclePart extends INode { readonly type: "lifecycle"; readonly timing: "layout" | "idle"; - readonly setups: SubscriptionTarget[]; + readonly setups: Tagged[]; } export interface RefPart extends INode { @@ -69,12 +69,12 @@ export interface ModifierPart extends INode { export interface DomResourcePart extends INode { readonly type: "resource:dom"; readonly timing: "layout" | "idle"; - readonly reactive: SubscriptionTarget; + readonly reactive: Tagged; } export interface ResourcePart extends INode { readonly type: "resource"; - readonly reactive: SubscriptionTarget; + readonly reactive: Tagged; } export type ComponentPart = diff --git a/packages/universal/interfaces/src/description.d.ts b/packages/universal/interfaces/src/description.d.ts index 831e2414..fd248c63 100644 --- a/packages/universal/interfaces/src/description.d.ts +++ b/packages/universal/interfaces/src/description.d.ts @@ -6,7 +6,7 @@ export interface DescriptionArgs { * An identifier for this description that is stable for the value that this description * describes. * - * For example, a `Cell` is allowed to return a new description each time its `[REACTIVE]` symbol + * For example, a `Cell` is allowed to return a new description each time its `[TAG]` symbol * is read, but the description must have the same `id` each time. */ readonly id?: ReactiveId | undefined; diff --git a/packages/universal/interfaces/src/frame.d.ts b/packages/universal/interfaces/src/frame.d.ts index dcc7765c..248d8770 100644 --- a/packages/universal/interfaces/src/frame.d.ts +++ b/packages/universal/interfaces/src/frame.d.ts @@ -1,7 +1,7 @@ import type { UNINITIALIZED } from "@starbeam/shared"; import type { Description } from "./description.js"; -import type { FormulaCore, SubscriptionTarget } from "./protocol.js"; +import type { FormulaTag, Tagged } from "./protocol.js"; export interface ValidFrame { readonly status: "valid"; @@ -15,7 +15,7 @@ export interface InvalidFrame { export type FrameValidation = ValidFrame | InvalidFrame; export interface Frame<_T = unknown> - extends SubscriptionTarget { + extends Tagged { readonly description: Description; validate: () => FrameValidation>; diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 277be4f6..4eb5a7ef 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -1,4 +1,4 @@ -import type { REACTIVE } from "@starbeam/shared"; +import type { TAG } from "@starbeam/shared"; import type { Description } from "./description.js"; import type { Stack } from "./stack.js"; @@ -6,7 +6,7 @@ import type { Timestamp } from "./timestamp.js"; export type ReactiveId = number | string | ReactiveId[]; -interface Core { +interface AbstractTag { readonly type: string; readonly description: Description; } @@ -15,7 +15,7 @@ interface Core { * Cell is the fundamental mutable reactive value. All subscriptions in Starbeam are ultimately * subscriptions to cells, and all mutations in Starbeam are ultimately mutations to cells. */ -export interface CellCore extends Core { +export interface CellTag extends AbstractTag { readonly type: "mutable"; readonly lastUpdated: Timestamp; isFrozen?: () => boolean; @@ -33,9 +33,9 @@ export interface CellCore extends Core { * notified of a change to the composite's children, it removes subscriptions from any stale * dependencies and adds subscriptions to any new dependencies. */ -export interface FormulaCore extends Core { - readonly type: "composite"; - children: () => SubscriptionTarget[]; +export interface FormulaTag extends AbstractTag { + readonly type: "formula"; + children: () => Tagged[]; } /** @@ -47,9 +47,9 @@ export interface FormulaCore extends Core { * targets. This means that delegates don't need to know when their value changes, and don't need to * notify the timeline when their targets change. */ -export interface DelegateCore extends Core { +export interface DelegateTag extends AbstractTag { readonly type: "delegate"; - readonly targets: readonly SubscriptionTarget[]; + readonly targets: readonly Tagged[]; } /** @@ -64,20 +64,19 @@ export interface DelegateCore extends Core { * TODO: Do we need a separate fundamental type for pollable formulas, which can get new * dependencies even if they never invalidate? */ -export interface StaticCore extends Core { +export interface StaticTag extends AbstractTag { readonly type: "static"; } -export type ReactiveCore = CellCore | FormulaCore | DelegateCore | StaticCore; +export type Tag = CellTag | FormulaTag | DelegateTag | StaticTag; +export type TagType = Tag["type"]; -export interface SubscriptionTarget { - [REACTIVE]: I; +export interface Tagged { + [TAG]: I; } -export interface ReactiveValue< - T = unknown, - I extends ReactiveCore = ReactiveCore -> extends SubscriptionTarget { +export interface ReactiveValue + extends Tagged { read: (stack?: Stack) => T; } @@ -85,6 +84,6 @@ export interface Reactive extends ReactiveValue { readonly current: T; } -export interface ReactiveCell extends Reactive { +export interface ReactiveCell extends Reactive { current: T; } diff --git a/packages/universal/js/src/collection.ts b/packages/universal/js/src/collection.ts index 71514a8c..f63baf27 100644 --- a/packages/universal/js/src/collection.ts +++ b/packages/universal/js/src/collection.ts @@ -1,5 +1,5 @@ import type { Description, Stack } from "@starbeam/debug"; -import { SubscriptionTarget } from "@starbeam/timeline"; +import { Tagged } from "@starbeam/timeline"; import { Cell, Marker } from "@starbeam/universal"; import { expected, isPresent, verified } from "@starbeam/verify"; @@ -203,7 +203,7 @@ export class Collection { } let item: Item; - const iteration = SubscriptionTarget.description(this.#iteration); + const iteration = Tagged.description(this.#iteration); if (disposition === "miss") { item = Item.uninitialized(iteration, member, caller); diff --git a/packages/universal/modifier/src/modifier.ts b/packages/universal/modifier/src/modifier.ts index 38b56b29..83b870e3 100644 --- a/packages/universal/modifier/src/modifier.ts +++ b/packages/universal/modifier/src/modifier.ts @@ -1,7 +1,7 @@ import type { anydom } from "@domtree/flavors"; import { type Description, REUSE_ID } from "@starbeam/debug"; -import type { SubscriptionTarget } from "@starbeam/interfaces"; -import { REACTIVE, UNINITIALIZED } from "@starbeam/shared"; +import type { Tagged } from "@starbeam/interfaces"; +import { TAG, UNINITIALIZED } from "@starbeam/shared"; import { Cell, DelegateInternals } from "@starbeam/universal"; import { expected, isPresent, verified, verify } from "@starbeam/verify"; @@ -14,7 +14,7 @@ export type ElementType = abstract new < // export type Ref = Initializable; export interface ElementPlaceholder - extends SubscriptionTarget { + extends Tagged { readonly initialize: (value: E) => void; readonly current: E | null; } @@ -35,7 +35,7 @@ export function ElementPlaceholder( REFS.set(ref, elementCell); return { - [REACTIVE]: DelegateInternals([elementCell]), + [TAG]: DelegateInternals([elementCell]), initialize(value: anydom.Element): void { const element = verified(REFS.get(ref), isPresent); diff --git a/packages/universal/shared/index.ts b/packages/universal/shared/index.ts index db5a8edd..466123c5 100644 --- a/packages/universal/shared/index.ts +++ b/packages/universal/shared/index.ts @@ -1,3 +1,3 @@ -export { COORDINATION, REACTIVE, UNINITIALIZED } from "./src/constants.js"; +export { COORDINATION, TAG, UNINITIALIZED } from "./src/constants.js"; export { getID } from "./src/id.js"; export { bump, now } from "./src/now.js"; diff --git a/packages/universal/shared/src/constants.ts b/packages/universal/shared/src/constants.ts index 4d81e9f4..4dc31f87 100644 --- a/packages/universal/shared/src/constants.ts +++ b/packages/universal/shared/src/constants.ts @@ -9,11 +9,11 @@ const UNINITIALIZED = Symbol.for("starbeam.UNINITIALIZED"); type UNINITIALIZED = typeof UNINITIALIZED; /** - * The `REACTIVE` symbol is the protocol entry point for reactive values. Implementations of - * the `ReactiveProtocol` interface specify their reactive behavior under this symbol. + * The `TAG` symbol is the protocol entry point for reactive values. Implementations of the `Tagged` + * interface specify their reactive behavior under this symbol. */ -const REACTIVE: unique symbol = Symbol.for("starbeam.REACTIVE"); -type REACTIVE = typeof REACTIVE; +const TAG: unique symbol = Symbol.for("starbeam.TAG"); +type TAG = typeof TAG; /** * The `NOW` symbol is the name on `globalThis` that is used to store the current timestamp. @@ -21,4 +21,4 @@ type REACTIVE = typeof REACTIVE; const COORDINATION: unique symbol = Symbol.for("starbeam.COORDINATION"); type COORDINATION = typeof COORDINATION; -export { COORDINATION, REACTIVE, UNINITIALIZED }; +export { COORDINATION, TAG, UNINITIALIZED }; diff --git a/packages/universal/shared/tests/constants.spec.ts b/packages/universal/shared/tests/constants.spec.ts index 9a78529e..8a1ecb69 100644 --- a/packages/universal/shared/tests/constants.spec.ts +++ b/packages/universal/shared/tests/constants.spec.ts @@ -1,9 +1,9 @@ -import { COORDINATION, REACTIVE, UNINITIALIZED } from "@starbeam/shared"; +import { COORDINATION, TAG, UNINITIALIZED } from "@starbeam/shared"; import { describe, expect, test } from "vitest"; describe("symbols", () => { testSymbol(UNINITIALIZED, "UNINITIALIZED"); - testSymbol(REACTIVE, "REACTIVE"); + testSymbol(TAG, "TAG"); testSymbol(COORDINATION, "COORDINATION"); }); diff --git a/packages/universal/timeline/index.ts b/packages/universal/timeline/index.ts index 6fa25f73..de54f50c 100644 --- a/packages/universal/timeline/index.ts +++ b/packages/universal/timeline/index.ts @@ -19,8 +19,8 @@ export { } from "./src/timeline/frame.js"; export { Reactive, - ReactiveCore as ReactiveInternals, - SubscriptionTarget, + Tag as ReactiveInternals, + Tagged as Tagged, } from "./src/timeline/protocol.js"; export { type NotifyReady, @@ -29,7 +29,7 @@ export { export { INSPECT } from "./src/timeline/timestamp.js"; export { max, getNow as now, zero } from "./src/timeline/timestamp.js"; export { diff } from "./src/timeline/utils.js"; -export { REACTIVE } from "@starbeam/shared"; +export { TAG } from "@starbeam/shared"; import type * as interfaces from "@starbeam/interfaces"; diff --git a/packages/universal/timeline/src/timeline/frame.ts b/packages/universal/timeline/src/timeline/frame.ts index 9496d893..23210834 100644 --- a/packages/universal/timeline/src/timeline/frame.ts +++ b/packages/universal/timeline/src/timeline/frame.ts @@ -1,32 +1,30 @@ import type { - CellCore, + CellTag, Description, - FormulaCore, + FormulaTag, Frame as IFrame, Timestamp, } from "@starbeam/interfaces"; -import { REACTIVE, UNINITIALIZED } from "@starbeam/shared"; +import { TAG, UNINITIALIZED } from "@starbeam/shared"; import { isNotEqual, verified } from "@starbeam/verify"; import type { FrameStack } from "./frames.js"; import { getID } from "./id.js"; -import { SubscriptionTarget } from "./protocol.js"; +import { Tagged } from "./protocol.js"; import type { Timeline } from "./timeline.js"; import { getNow } from "./timestamp.js"; interface Marker { - [REACTIVE]: Omit & { + [TAG]: Omit & { lastUpdated: Timestamp; }; } -export class Frame - implements SubscriptionTarget, IFrame -{ +export class Frame implements Tagged, IFrame { static create( this: void, value: T, - children: Set, + children: Set, finalized: Timestamp, description: Description ): Frame { @@ -35,7 +33,7 @@ export class Frame return new Frame( value, { - [REACTIVE]: { + [TAG]: { type: "mutable", lastUpdated: finalized, description: description @@ -58,7 +56,7 @@ export class Frame return new Frame( UNINITIALIZED, { - [REACTIVE]: { + [TAG]: { type: "mutable", lastUpdated: finalized, description: description.detail("initialized?", { id }), @@ -82,7 +80,7 @@ export class Frame this: void, frame: Frame, value: T, - children: Set, + children: Set, finalized: Timestamp ): Frame { return frame.#update(value, children, finalized); @@ -91,25 +89,25 @@ export class Frame static updateChildren( this: void, frame: Frame, - children: Set + children: Set ): void { frame.#children = children; } #value: T | UNINITIALIZED; readonly #initialized: Marker; - #children: ReadonlySet; + #children: ReadonlySet; #finalized: Timestamp; readonly #description: Description; constructor( value: T | UNINITIALIZED, initialized: { - [REACTIVE]: Omit & { + [TAG]: Omit & { lastUpdated: Timestamp; }; }, - children: Set, + children: Set, finalized: Timestamp, description: Description ) { @@ -120,11 +118,11 @@ export class Frame this.#description = description; } - get [REACTIVE](): FormulaCore { + get [TAG](): FormulaTag { return { - type: "composite", + type: "formula", description: this.#description, - children: (): SubscriptionTarget[] => { + children: (): Tagged[] => { return [this.#initialized, ...this.#children]; }, }; @@ -149,13 +147,9 @@ export class Frame } } - #update( - value: T, - children: Set, - finalized: Timestamp - ): this { + #update(value: T, children: Set, finalized: Timestamp): this { if (Object.is(this.#value, UNINITIALIZED)) { - this.#initialized[REACTIVE].lastUpdated = finalized; + this.#initialized[TAG].lastUpdated = finalized; } this.#value = value; @@ -167,7 +161,7 @@ export class Frame validate(): FrameValidation> { if ( this.#value === UNINITIALIZED || - SubscriptionTarget.lastUpdatedIn([...this.#children]).gt(this.#finalized) + Tagged.lastUpdatedIn([...this.#children]).gt(this.#finalized) ) { return { status: "invalid" }; } else { @@ -190,12 +184,12 @@ export class ActiveFrame { readonly #updating: Frame | null; readonly #prev: ActiveFrame | null; - readonly #children: Set; + readonly #children: Set; private constructor( updating: Frame | null, prev: ActiveFrame | null, - children: Set, + children: Set, readonly description: Description ) { this.#updating = updating; @@ -203,7 +197,7 @@ export class ActiveFrame { this.#children = children; } - add(child: SubscriptionTarget): void { + add(child: Tagged): void { this.#children.add(child); } diff --git a/packages/universal/timeline/src/timeline/frames.ts b/packages/universal/timeline/src/timeline/frames.ts index e3fa5895..e251476c 100644 --- a/packages/universal/timeline/src/timeline/frames.ts +++ b/packages/universal/timeline/src/timeline/frames.ts @@ -1,10 +1,10 @@ import type { DebugTimeline, Stack } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { CellCore } from "@starbeam/interfaces"; -import { REACTIVE } from "@starbeam/shared"; +import type { CellTag } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; import { ActiveFrame, type Frame } from "./frame.js"; -import { SubscriptionTarget } from "./protocol.js"; +import { Tagged } from "./protocol.js"; import type { Subscriptions } from "./subscriptions.js"; import type { Timeline } from "./timeline.js"; @@ -15,17 +15,17 @@ export class FrameStack { static didConsumeCell( frames: FrameStack, - reactive: SubscriptionTarget, + reactive: Tagged, caller: Stack ): void { - frames.#debug.consumeCell(reactive[REACTIVE], caller); + frames.#debug.consumeCell(reactive[TAG], caller); frames.#didConsumeReactive(reactive, caller); } static didConsumeFrame( frames: FrameStack, frame: interfaces.Frame, - diff: interfaces.Diff, + diff: interfaces.Diff, caller: Stack ): void { frames.#debug.consumeFrame(frame, diff, caller); @@ -90,18 +90,18 @@ export class FrameStack { return this.#start(description) as ActiveFrame; } - #didConsumeReactive(reactive: SubscriptionTarget, caller: Stack): void { + #didConsumeReactive(reactive: Tagged, caller: Stack): void { const frame = this.currentFrame; if (frame) { frame.add(reactive); return; } else { - const delegatesTo = SubscriptionTarget.subscriptionTargets( - reactive - ).filter((r) => SubscriptionTarget.is(r, "mutable")); + const delegatesTo = Tagged.subscriptionTargets(reactive).filter((r) => + Tagged.is(r, "mutable") + ); for (const target of delegatesTo) { - if (SubscriptionTarget.is(target, "mutable")) { + if (Tagged.is(target, "mutable")) { this.#timeline.untrackedRead(target, caller); } } diff --git a/packages/universal/timeline/src/timeline/protocol.ts b/packages/universal/timeline/src/timeline/protocol.ts index e9f4e536..77233fb9 100644 --- a/packages/universal/timeline/src/timeline/protocol.ts +++ b/packages/universal/timeline/src/timeline/protocol.ts @@ -1,59 +1,49 @@ import type * as Debug from "@starbeam/debug"; import { Desc, Tree } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { - CellCore, - DelegateCore, - FormulaCore, - StaticCore, -} from "@starbeam/interfaces"; -import { REACTIVE } from "@starbeam/shared"; +import { TAG } from "@starbeam/shared"; import { isPresent } from "@starbeam/verify"; import { Timestamp, zero } from "./timestamp.js"; export type Reactive = interfaces.Reactive; -interface ExhaustiveMatcher { - mutable: (internals: CellCore) => T; - composite: (internals: FormulaCore) => T; - delegate: (internals: DelegateCore) => T; - static: (internals: StaticCore) => T; -} +type ExhaustiveMatcher = { + [P in interfaces.TagType]: (tag: Extract) => T; +}; -export type ReactiveCore = interfaces.ReactiveCore; +export type Tag = interfaces.Tag; interface DefaultMatcher extends Partial> { - default: (internals: ReactiveCore) => T; + default: (internals: Tag) => T; } type Matcher = ExhaustiveMatcher | DefaultMatcher; -export type SubscriptionTarget< - I extends interfaces.ReactiveCore = interfaces.ReactiveCore -> = interfaces.SubscriptionTarget; +export type Tagged = + interfaces.Tagged; -export const SubscriptionTarget = { - description(this: void, reactive: SubscriptionTarget): Debug.Description { - return ReactiveCore.description(reactive[REACTIVE]); +export const Tagged = { + description(this: void, reactive: Tagged): Debug.Description { + return Tag.description(reactive[TAG]); }, - id(this: void, reactive: SubscriptionTarget): interfaces.ReactiveId { - return ReactiveCore.id(reactive[REACTIVE]); + id(this: void, reactive: Tagged): interfaces.ReactiveId { + return Tag.id(reactive[TAG]); }, - is( + is( this: void, - reactive: SubscriptionTarget, + reactive: Tagged, kind: T ): reactive is { - [REACTIVE]: Extract; + [TAG]: Extract; } { - return ReactiveCore.is(reactive[REACTIVE], kind); + return Tag.is(reactive[TAG], kind); }, - match(this: void, reactive: SubscriptionTarget, matcher: Matcher): T { - return ReactiveCore.match(reactive[REACTIVE], matcher); + match(this: void, reactive: Tagged, matcher: Matcher): T { + return Tag.match(reactive[TAG], matcher); }, /** @@ -69,44 +59,38 @@ export const SubscriptionTarget = { * This makes it possible to create abstractions around reactive values that don't have to worry * about manually updating their subscribers when their values change. */ - subscriptionTargets( - this: void, - reactive: SubscriptionTarget - ): SubscriptionTarget[] { - const internals = reactive[REACTIVE]; + subscriptionTargets(this: void, reactive: Tagged): Tagged[] { + const internals = reactive[TAG]; console.log({ internals }); if (internals.type === "delegate") { - return internals.targets.flatMap(SubscriptionTarget.subscriptionTargets); + return internals.targets.flatMap(Tagged.subscriptionTargets); } else { return [reactive]; } }, - dependencies( - this: void, - reactive: SubscriptionTarget - ): Iterable { - return ReactiveCore.dependencies(reactive[REACTIVE]); + dependencies(this: void, reactive: Tagged): Iterable { + return Tag.dependencies(reactive[TAG]); }, *dependenciesInList( this: void, - children: readonly SubscriptionTarget[] - ): Iterable { + children: readonly Tagged[] + ): Iterable { for (const child of children) { - yield* ReactiveCore.dependencies(child[REACTIVE]); + yield* Tag.dependencies(child[TAG]); } }, - lastUpdated(this: void, reactive: SubscriptionTarget): Timestamp { - return ReactiveCore.lastUpdated(reactive[REACTIVE]); + lastUpdated(this: void, reactive: Tagged): Timestamp { + return Tag.lastUpdated(reactive[TAG]); }, - lastUpdatedIn(this: void, reactives: SubscriptionTarget[]): Timestamp { + lastUpdatedIn(this: void, reactives: Tagged[]): Timestamp { let lastUpdatedTimestamp = zero(); - for (const child of SubscriptionTarget.dependenciesInList(reactives)) { + for (const child of Tagged.dependenciesInList(reactives)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } @@ -117,37 +101,37 @@ export const SubscriptionTarget = { log( this: void, - reactive: SubscriptionTarget, + reactive: Tagged, options: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): void { - ReactiveCore.log(reactive[REACTIVE], options); + Tag.log(reactive[TAG], options); }, debug( this: void, - reactive: SubscriptionTarget, + reactive: Tagged, { implementation = false, source = false, }: { implementation?: boolean; source?: boolean } = {} ): string { - return ReactiveCore.debug(reactive[REACTIVE], { + return Tag.debug(reactive[TAG], { implementation, source, }); }, } as const; -export const ReactiveCore = { - is( +export const Tag = { + is( this: void, - internals: interfaces.ReactiveCore, + internals: interfaces.Tag, kind: T - ): internals is Extract { + ): internals is Extract { return internals.type === kind; }, - id(this: void, internals: interfaces.ReactiveCore): interfaces.ReactiveId { + id(this: void, internals: interfaces.Tag): interfaces.ReactiveId { return internals.description.id; }, @@ -157,9 +141,7 @@ export const ReactiveCore = { * This list is only valid until the next time anyone reads from the reactive. It's intended to be * used along with code that updates the dependencies whenever the reactive is read. */ - *dependencies( - internals: interfaces.ReactiveCore - ): Iterable { + *dependencies(internals: interfaces.Tag): Iterable { switch (internals.type) { case "static": return; @@ -171,52 +153,49 @@ export const ReactiveCore = { yield internals; break; case "delegate": - for (const target of ReactiveCore.subscribesTo(internals)) { - yield* ReactiveCore.dependencies(target); + for (const target of Tag.subscribesTo(internals)) { + yield* Tag.dependencies(target); } break; - case "composite": - yield* SubscriptionTarget.dependenciesInList(internals.children()); + case "formula": + yield* Tagged.dependenciesInList(internals.children()); break; } }, *dependenciesInList( this: void, - children: readonly interfaces.ReactiveCore[] - ): Iterable { + children: readonly interfaces.Tag[] + ): Iterable { for (const child of children) { - yield* ReactiveCore.dependencies(child); + yield* Tag.dependencies(child); } }, - subscribesTo( - this: void, - internals: interfaces.ReactiveCore - ): interfaces.ReactiveCore[] { + subscribesTo(this: void, internals: interfaces.Tag): interfaces.Tag[] { if (internals.type === "delegate") { return internals.targets.flatMap((protocol) => - SubscriptionTarget.subscriptionTargets(protocol).map((p) => p[REACTIVE]) + Tagged.subscriptionTargets(protocol).map((p) => p[TAG]) ); } else { return [internals]; } }, - lastUpdated(this: void, internals: interfaces.ReactiveCore): Timestamp { + lastUpdated(this: void, internals: interfaces.Tag): Timestamp { switch (internals.type) { case "static": return zero(); case "mutable": return internals.lastUpdated; case "delegate": { - const delegates = ReactiveCore.subscribesTo(internals); - return ReactiveCore.lastUpdatedIn(delegates); + const delegates = Tag.subscribesTo(internals); + return Tag.lastUpdatedIn(delegates); } - case "composite": { + case "formula": { let lastUpdatedTimestamp = zero(); - for (const child of ReactiveCore.dependencies(internals)) { + for (const child of Tag.dependencies(internals)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } @@ -227,10 +206,10 @@ export const ReactiveCore = { } }, - lastUpdatedIn(this: void, core: ReactiveCore[]): Timestamp { + lastUpdatedIn(this: void, core: Tag[]): Timestamp { let lastUpdatedTimestamp = zero(); - for (const child of ReactiveCore.dependenciesInList(core)) { + for (const child of Tag.dependenciesInList(core)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } @@ -239,20 +218,20 @@ export const ReactiveCore = { return lastUpdatedTimestamp; }, - description(this: void, core: ReactiveCore): Debug.Description { + description(this: void, core: Tag): Debug.Description { return core.description; }, debug( this: void, - internals: ReactiveCore, + internals: Tag, { implementation = false, source = false, id = false, }: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): string { - const dependencies = [...ReactiveCore.dependencies(internals)]; + const dependencies = [...Tag.dependencies(internals)]; const descriptions = new Set( dependencies.map((dependency) => { return implementation @@ -273,24 +252,20 @@ export const ReactiveCore = { log( this: void, - internals: interfaces.ReactiveCore, + internals: interfaces.Tag, options: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): void { - const debug = ReactiveCore.debug(internals, options); + const debug = Tag.debug(internals, options); console.group( - ReactiveCore.description(internals).describe({ id: options.id }), - `(updated at ${Timestamp.debug(ReactiveCore.lastUpdated(internals)).at})` + Tag.description(internals).describe({ id: options.id }), + `(updated at ${Timestamp.debug(Tag.lastUpdated(internals)).at})` ); console.log(debug); console.groupEnd(); }, - match( - this: void, - internals: interfaces.ReactiveCore, - matcher: Matcher - ): T { + match(this: void, internals: interfaces.Tag, matcher: Matcher): T { const fn = matcher[internals.type]; if (typeof fn === "function") { return fn(internals as never); @@ -307,26 +282,10 @@ function is( return !!( value && (typeof value === "object" || typeof value === "function") && - REACTIVE in value + TAG in value ); } -// export const SubscriptionTarget = { -// is, - -// from( -// this: void, -// value: T | Reactive, -// description?: string | Debug.Description -// ): Reactive { -// if (is(value)) { -// return value; -// } else { -// return new Static(value, Desc("static", description)); -// } -// }, -// }; - export const Reactive = { is(this: void, value: unknown): value is interfaces.Reactive { return is(value) && hasRead(value); @@ -349,13 +308,13 @@ function hasRead(value: object): value is { read: () => T } { return "read" in value && typeof value.read === "function"; } -class Static implements interfaces.ReactiveValue { +class Static implements interfaces.ReactiveValue { readonly #value: T; - readonly [REACTIVE]: interfaces.StaticCore; + readonly [TAG]: interfaces.StaticTag; constructor(value: T, description: Debug.Description) { this.#value = value; - this[REACTIVE] = { + this[TAG] = { type: "static", description, }; diff --git a/packages/universal/timeline/src/timeline/subscriptions.ts b/packages/universal/timeline/src/timeline/subscriptions.ts index 92ded9af..d9585b00 100644 --- a/packages/universal/timeline/src/timeline/subscriptions.ts +++ b/packages/universal/timeline/src/timeline/subscriptions.ts @@ -1,10 +1,10 @@ -import type { CellCore, Diff, FormulaCore } from "@starbeam/interfaces"; +import type { CellTag, Diff, FormulaTag } from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; -import { SubscriptionTarget } from "./protocol.js"; +import { Tagged } from "./protocol.js"; import { diff } from "./utils.js"; -export type NotifyReady = (internals: CellCore) => void; +export type NotifyReady = (internals: CellTag) => void; /** * A subscription is a weak mapping from individual cells to the subscriptions that depend on them. @@ -69,12 +69,12 @@ export class Subscriptions { * we may want to fire notifications whenever a `PolledFormula` is recomputed and produces * different dependencies. */ - register(target: SubscriptionTarget, ready: NotifyReady): Unsubscribe { - const subscriptionTargets = SubscriptionTarget.subscriptionTargets(target); + register(target: Tagged, ready: NotifyReady): Unsubscribe { + const subscriptionTargets = Tagged.subscriptionTargets(target); const unsubscribes = subscriptionTargets.map((t) => { const entry = this.#formulaMap.register(t); - for (const dependency of SubscriptionTarget.dependencies(t)) { + for (const dependency of Tagged.dependencies(t)) { this.#cellMap.register(dependency, entry); } @@ -91,7 +91,7 @@ export class Subscriptions { /** * Notify the subscribers of a particular cell. This happens synchronously during mutation. */ - notify(mutable: CellCore): void { + notify(mutable: CellTag): void { this.#cellMap.notify(mutable); } @@ -100,7 +100,7 @@ export class Subscriptions { * results in removing mappings from cells that are no longer dependencies and adding mappings for * cells that have become dependencies. */ - update(frame: SubscriptionTarget): void { + update(frame: Tagged): void { const cellMap = this.#cellMap; const { add, remove, entry } = this.#formulaMap.update(frame); @@ -117,11 +117,11 @@ class FormulaMap { return new FormulaMap(); } - readonly #mapping = new WeakMap(); + readonly #mapping = new WeakMap(); update( - frame: SubscriptionTarget - ): Diff & { entry: ReactiveSubscription } { + frame: Tagged + ): Diff & { entry: ReactiveSubscription } { const entry = this.#mapping.get(frame); if (entry) { @@ -130,14 +130,14 @@ class FormulaMap { const entry = ReactiveSubscription.create(frame); this.#mapping.set(frame, entry); return { - add: new Set(SubscriptionTarget.dependencies(frame)), + add: new Set(Tagged.dependencies(frame)), remove: new Set(), entry, }; } } - register(target: SubscriptionTarget): ReactiveSubscription { + register(target: Tagged): ReactiveSubscription { let entry = this.#mapping.get(target); if (!entry) { @@ -150,15 +150,15 @@ class FormulaMap { } class ReactiveSubscription { - static create(target: SubscriptionTarget): ReactiveSubscription { - const deps = new Set(SubscriptionTarget.dependencies(target)); + static create(target: Tagged): ReactiveSubscription { + const deps = new Set(Tagged.dependencies(target)); return new ReactiveSubscription(deps); } - #deps: Set; + #deps: Set; readonly #ready = new Set(); - private constructor(deps: Set) { + private constructor(deps: Set) { this.#deps = deps; } @@ -167,15 +167,15 @@ class ReactiveSubscription { return () => this.#ready.delete(ready); } - notify(internals: CellCore): void { + notify(internals: CellTag): void { for (const ready of this.#ready) { ready(internals); } } - update(frame: SubscriptionTarget): Diff { + update(frame: Tagged): Diff { const prev = this.#deps; - const next = new Set(SubscriptionTarget.dependencies(frame)); + const next = new Set(Tagged.dependencies(frame)); this.#deps = next; return diff(prev, next); @@ -193,31 +193,31 @@ class CellMap { return new CellMap(); } - readonly #entriesMap = new WeakMap>(); + readonly #entriesMap = new WeakMap>(); - remove(mutables: ReadonlySet, entry: ReactiveSubscription): void { + remove(mutables: ReadonlySet, entry: ReactiveSubscription): void { for (const mutable of mutables) { this.#entriesMap.get(mutable)?.delete(entry); } } - add(mutables: ReadonlySet, entry: ReactiveSubscription): void { + add(mutables: ReadonlySet, entry: ReactiveSubscription): void { for (const mutable of mutables) { this.#initialized(mutable).add(entry); } } - register(mutable: CellCore, entry: ReactiveSubscription): void { + register(mutable: CellTag, entry: ReactiveSubscription): void { this.#initialized(mutable).add(entry); } - notify(mutable: CellCore): void { + notify(mutable: CellTag): void { for (const entry of this.#entries(mutable)) { entry.notify(mutable); } } - *#entries(mutable: CellCore): IterableIterator { + *#entries(mutable: CellTag): IterableIterator { const entries = this.#entriesMap.get(mutable); if (entries) { @@ -225,7 +225,7 @@ class CellMap { } } - #initialized(mutable: CellCore): Set { + #initialized(mutable: CellTag): Set { let entries = this.#entriesMap.get(mutable); if (!entries) { diff --git a/packages/universal/timeline/src/timeline/timeline.ts b/packages/universal/timeline/src/timeline/timeline.ts index 2503a233..907b5d53 100644 --- a/packages/universal/timeline/src/timeline/timeline.ts +++ b/packages/universal/timeline/src/timeline/timeline.ts @@ -1,11 +1,11 @@ import type { Stack } from "@starbeam/debug"; import { DebugTimeline } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { CellCore } from "@starbeam/interfaces"; +import type { CellTag } from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { FrameStack } from "./frames.js"; -import { SubscriptionTarget } from "./protocol.js"; +import { Tagged } from "./protocol.js"; import { type NotifyReady, Subscriptions } from "./subscriptions.js"; import { getNow, NOW } from "./timestamp.js"; @@ -42,7 +42,7 @@ export class Timeline { readonly #frame: FrameStack; on = { - change: (target: SubscriptionTarget, ready: NotifyReady): Unsubscribe => { + change: (target: Tagged, ready: NotifyReady): Unsubscribe => { return this.#subscriptions.register(target, ready); }, } as const; @@ -51,9 +51,7 @@ export class Timeline { * Dynamic assertions that are used in development mode to detect reads that occur outside of a * tracking frame, but which are used to produce rendered outputs. */ - #readAssertions = new Set< - (reactive: SubscriptionTarget, caller: Stack) => void - >(); + #readAssertions = new Set<(reactive: Tagged, caller: Stack) => void>(); readonly #subscriptions: Subscriptions; #lastOp: TimelineOp; @@ -64,7 +62,7 @@ export class Timeline { * produce rendered content. */ declare untrackedReadBarrier: ( - assertion: (reactive: SubscriptionTarget, caller: Stack) => void + assertion: (reactive: Tagged, caller: Stack) => void ) => void; static create(): Timeline { @@ -78,7 +76,7 @@ export class Timeline { if (import.meta.env.DEV) { this.untrackedReadBarrier = ( - assertion: (reactive: SubscriptionTarget, caller: Stack) => void + assertion: (reactive: Tagged, caller: Stack) => void ): void => { this.#readAssertions.add(assertion); }; @@ -87,10 +85,7 @@ export class Timeline { get #debug(): DebugTimeline { if (!this.#debugTimeline) { - this.#debugTimeline = DebugTimeline.create( - { now: getNow }, - SubscriptionTarget - ); + this.#debugTimeline = DebugTimeline.create({ now: getNow }, Tagged); } return this.#debugTimeline; @@ -124,7 +119,7 @@ export class Timeline { } } - bump(mutable: interfaces.CellCore, caller: Stack): interfaces.Timestamp { + bump(mutable: interfaces.CellTag, caller: Stack): interfaces.Timestamp { const now = this.#adjustTimestamp("bumped"); if (import.meta.env.DEV) { @@ -135,14 +130,14 @@ export class Timeline { return now; } - didConsumeCell(cell: SubscriptionTarget, caller: Stack): void { + didConsumeCell(cell: Tagged, caller: Stack): void { this.#adjustTimestamp("consumed"); FrameStack.didConsumeCell(this.#frame, cell, caller); } didConsumeFrame( frame: interfaces.Frame, - diff: interfaces.Diff, + diff: interfaces.Diff, caller: Stack ): void { this.#adjustTimestamp("consumed"); @@ -164,9 +159,7 @@ export class Timeline { * For example, Formulas call this method after recomputing their value, which results in a * possible change to their dependencies. */ - update( - reactive: interfaces.SubscriptionTarget - ): void { + update(reactive: interfaces.Tagged): void { this.#subscriptions.update(reactive); } @@ -185,7 +178,7 @@ export class Timeline { /// DEBUG MODE /// /** @internal */ - untrackedRead(cell: SubscriptionTarget, caller: Stack): void { + untrackedRead(cell: Tagged, caller: Stack): void { for (const assertion of this.#readAssertions) { assertion(cell, caller); } diff --git a/packages/universal/timeline/tests/pollable.spec.ts b/packages/universal/timeline/tests/pollable.spec.ts index ad87d969..aff441fe 100644 --- a/packages/universal/timeline/tests/pollable.spec.ts +++ b/packages/universal/timeline/tests/pollable.spec.ts @@ -1,7 +1,7 @@ import { isPresentArray } from "@starbeam/core-utils"; import { descriptionFrom } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; -import { Frame, REACTIVE, TIMELINE } from "@starbeam/timeline"; +import { Frame, TAG, TIMELINE } from "@starbeam/timeline"; import { describe, expect, test } from "vitest"; import { Cell } from "./support/mini-reactives.js"; @@ -62,7 +62,7 @@ describe("pollable", () => { const delegate: ReactiveValue = { read: () => cell.current, - [REACTIVE]: { + [TAG]: { type: "delegate", description: descriptionFrom({ type: "delegate", @@ -93,7 +93,7 @@ describe("pollable", () => { const delegate: ReactiveValue = { read: () => sum.read(), - [REACTIVE]: { + [TAG]: { type: "delegate", description: descriptionFrom({ type: "delegate", @@ -160,7 +160,7 @@ function Sum(): { ) ); }, - [REACTIVE]: { + [TAG]: { type: "delegate", description: descriptionFrom({ type: "delegate", diff --git a/packages/universal/timeline/tests/protocol.spec.ts b/packages/universal/timeline/tests/protocol.spec.ts index 694c9b08..6d415c3b 100644 --- a/packages/universal/timeline/tests/protocol.spec.ts +++ b/packages/universal/timeline/tests/protocol.spec.ts @@ -1,16 +1,11 @@ import { callerStack, descriptionFrom } from "@starbeam/debug"; -import type { FormulaCore } from "@starbeam/interfaces"; -import { - REACTIVE, - SubscriptionTarget, - TIMELINE, - zero, -} from "@starbeam/timeline"; +import type { FormulaTag } from "@starbeam/interfaces"; +import { TAG, Tagged, TIMELINE, zero } from "@starbeam/timeline"; import { beforeAll, describe, expect, it } from "vitest"; import { Cell, FreezableCell, Static } from "./support/mini-reactives.js"; -describe("SubscriptionTarget", () => { +describe("Tagged", () => { beforeAll(() => { // make sure the timeline is not at 0, which would make a comparison with TIMELINE.now sometimes // equivalent to Timestamp.zero(), and we want to test the difference. @@ -30,17 +25,15 @@ describe("SubscriptionTarget", () => { it("has the zero timestamp for lastUpdated", () => { const tom = Static("Tom Dale"); - expect(String(SubscriptionTarget.lastUpdated(tom))).toBe(String(zero())); - expect(String(SubscriptionTarget.lastUpdatedIn([tom]))).toBe( - String(zero()) - ); + expect(String(Tagged.lastUpdated(tom))).toBe(String(zero())); + expect(String(Tagged.lastUpdatedIn([tom]))).toBe(String(zero())); }); it("has no dependencies", () => { const tom = Static("Tom Dale"); - expect([...SubscriptionTarget.dependencies(tom)]).toEqual([]); - expect([...SubscriptionTarget.dependenciesInList([tom])]).toEqual([]); + expect([...Tagged.dependencies(tom)]).toEqual([]); + expect([...Tagged.dependenciesInList([tom])]).toEqual([]); }); }); @@ -48,16 +41,14 @@ describe("SubscriptionTarget", () => { it("has the current timestamp for lastUpdated", () => { const original = TIMELINE.now; const tom = Cell("Tom"); - expect(String(SubscriptionTarget.lastUpdated(tom))).toBe( - String(TIMELINE.now) - ); + expect(String(Tagged.lastUpdated(tom))).toBe(String(TIMELINE.now)); const nullvox = Cell("nullvox"); const nullvoxTimestamp = TIMELINE.now; - expect(String(SubscriptionTarget.lastUpdated(nullvox))).toBe( + expect(String(Tagged.lastUpdated(nullvox))).toBe( String(nullvoxTimestamp) ); - expect(String(SubscriptionTarget.lastUpdatedIn([tom, nullvox]))).toBe( + expect(String(Tagged.lastUpdatedIn([tom, nullvox]))).toBe( String(TIMELINE.now) ); @@ -65,13 +56,11 @@ describe("SubscriptionTarget", () => { tom.current = "Tom Dale"; expect(String(TIMELINE.now)).not.toBe(String(original)); - expect(String(SubscriptionTarget.lastUpdated(tom))).toBe( - String(TIMELINE.now) - ); - expect(String(SubscriptionTarget.lastUpdated(nullvox))).toBe( + expect(String(Tagged.lastUpdated(tom))).toBe(String(TIMELINE.now)); + expect(String(Tagged.lastUpdated(nullvox))).toBe( String(nullvoxTimestamp) ); - expect(String(SubscriptionTarget.lastUpdatedIn([tom, nullvox]))).toBe( + expect(String(Tagged.lastUpdatedIn([tom, nullvox]))).toBe( String(TIMELINE.now) ); }); @@ -80,12 +69,11 @@ describe("SubscriptionTarget", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - expect([...SubscriptionTarget.dependencies(tom)]).toEqual([ - tom[REACTIVE], + expect([...Tagged.dependencies(tom)]).toEqual([tom[TAG]]); + expect([...Tagged.dependenciesInList([tom, nullvox])]).toEqual([ + tom[TAG], + nullvox[TAG], ]); - expect([ - ...SubscriptionTarget.dependenciesInList([tom, nullvox]), - ]).toEqual([tom[REACTIVE], nullvox[REACTIVE]]); }); it("has no dependencies if it's frozen", () => { @@ -95,10 +83,10 @@ describe("SubscriptionTarget", () => { nullvox.current = "@nullvoxpopuli"; - expect([...SubscriptionTarget.dependencies(tom)]).toEqual([]); - expect([ - ...SubscriptionTarget.dependenciesInList([tom, nullvox]), - ]).toEqual([nullvox[REACTIVE]]); + expect([...Tagged.dependencies(tom)]).toEqual([]); + expect([...Tagged.dependenciesInList([tom, nullvox])]).toEqual([ + nullvox[TAG], + ]); }); }); @@ -107,8 +95,8 @@ describe("SubscriptionTarget", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - const composite: FormulaCore = { - type: "composite", + const composite: FormulaTag = { + type: "formula", description: descriptionFrom({ type: "formula", api: "Composite", @@ -118,24 +106,17 @@ describe("SubscriptionTarget", () => { }, }; - const Both: SubscriptionTarget = { - [REACTIVE]: composite, + const Both: Tagged = { + [TAG]: composite, }; - expect(String(SubscriptionTarget.lastUpdated(Both))).toBe( - String(TIMELINE.now) - ); + expect(String(Tagged.lastUpdated(Both))).toBe(String(TIMELINE.now)); - expect([...SubscriptionTarget.dependencies(Both)]).toEqual([ - tom[REACTIVE], - nullvox[REACTIVE], - ]); + expect([...Tagged.dependencies(Both)]).toEqual([tom[TAG], nullvox[TAG]]); tom.current = "Tom Dale"; - expect(String(SubscriptionTarget.lastUpdated(Both))).toBe( - String(TIMELINE.now) - ); + expect(String(Tagged.lastUpdated(Both))).toBe(String(TIMELINE.now)); }); }); }); diff --git a/packages/universal/timeline/tests/support/mini-reactives.ts b/packages/universal/timeline/tests/support/mini-reactives.ts index b6db5ccf..4645edc0 100644 --- a/packages/universal/timeline/tests/support/mini-reactives.ts +++ b/packages/universal/timeline/tests/support/mini-reactives.ts @@ -5,12 +5,12 @@ import { type Stack, } from "@starbeam/debug"; import type { - CellCore, + CellTag, ReactiveCell, ReactiveValue, } from "@starbeam/interfaces"; -import { REACTIVE, type UNINITIALIZED } from "@starbeam/shared"; -import { type SubscriptionTarget } from "@starbeam/timeline"; +import { TAG, type UNINITIALIZED } from "@starbeam/shared"; +import { type Tagged } from "@starbeam/timeline"; import { diff, Frame, TIMELINE, type Timestamp } from "@starbeam/timeline"; export interface FreezableCell extends ReactiveCell { @@ -20,13 +20,13 @@ export interface FreezableCell extends ReactiveCell { export type Cell = ReactiveCell; class CellImpl implements ReactiveCell { - readonly [REACTIVE]: CellCore; + readonly [TAG]: CellTag; #value: T; #lastUpdated: Timestamp; constructor(value: T, timestamp: Timestamp) { const lastUpdated = (): Timestamp => this.#lastUpdated; - this[REACTIVE] = { + this[TAG] = { type: "mutable", description: Desc("cell"), get lastUpdated(): Timestamp { @@ -47,7 +47,7 @@ class CellImpl implements ReactiveCell { set current(newValue: T) { this.#value = newValue; - this.#lastUpdated = TIMELINE.bump(this[REACTIVE], callerStack()); + this.#lastUpdated = TIMELINE.bump(this[TAG], callerStack()); } } @@ -56,14 +56,14 @@ export function Cell(value: T): CellImpl { } class FreezableCellImpl implements ReactiveCell { - readonly [REACTIVE]: CellCore; + readonly [TAG]: CellTag; #isFrozen = false; #value: T; #lastUpdated: Timestamp; constructor(value: T, timestamp: Timestamp) { const lastUpdated = (): Timestamp => this.#lastUpdated; - this[REACTIVE] = { + this[TAG] = { type: "mutable", description: Desc("cell"), get lastUpdated(): Timestamp { @@ -85,7 +85,7 @@ class FreezableCellImpl implements ReactiveCell { set current(newValue: T) { this.#value = newValue; - this.#lastUpdated = TIMELINE.bump(this[REACTIVE], callerStack()); + this.#lastUpdated = TIMELINE.bump(this[TAG], callerStack()); } freeze(): void { @@ -99,7 +99,7 @@ export function FreezableCell(value: T): FreezableCellImpl { export function Static(value: T): ReactiveValue { return { - [REACTIVE]: { + [TAG]: { type: "static", description: descriptionFrom({ api: "Static", @@ -146,11 +146,11 @@ export function Formula(computation: () => T): { } export function Marker(): { - instance: SubscriptionTarget; + instance: Tagged; update: () => void; } { let lastUpdated = TIMELINE.next(); - const internals: CellCore = { + const internals: CellTag = { type: "mutable", description: descriptionFrom({ type: "cell", @@ -163,7 +163,7 @@ export function Marker(): { return { instance: { - [REACTIVE]: internals, + [TAG]: internals, }, update: () => { lastUpdated = TIMELINE.bump(internals, callerStack()); diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index da2b43d5..2cd6a56d 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -55,4 +55,4 @@ export { Variants, type VariantType, } from "./src/reactive-core/variants.js"; -export { LIFETIME, REACTIVE, TIMELINE } from "@starbeam/timeline"; +export { LIFETIME, TAG, TIMELINE } from "@starbeam/timeline"; diff --git a/packages/universal/universal/src/reactive-core/cell.ts b/packages/universal/universal/src/reactive-core/cell.ts index be701450..6d5b7194 100644 --- a/packages/universal/universal/src/reactive-core/cell.ts +++ b/packages/universal/universal/src/reactive-core/cell.ts @@ -9,7 +9,7 @@ import { import type * as interfaces from "@starbeam/interfaces"; import type { ReactiveValue } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import { INSPECT, REACTIVE, TIMELINE } from "@starbeam/timeline"; +import { INSPECT, TAG, TIMELINE } from "@starbeam/timeline"; import type { MutableInternalsImpl } from "../storage.js"; import { MutableInternals } from "../storage.js"; @@ -21,7 +21,7 @@ export interface CellPolicy { export type Equality = (a: T, b: T) => boolean; -export class ReactiveCell implements ReactiveValue { +export class ReactiveCell implements ReactiveValue { static create( value: T, internals: MutableInternalsImpl, @@ -113,7 +113,7 @@ export class ReactiveCell implements ReactiveValue { return true; } - get [REACTIVE](): MutableInternals { + get [TAG](): MutableInternals { return this.#internals; } } diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/universal/src/reactive-core/delegate.ts index 05a89177..ed59975c 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/universal/src/reactive-core/delegate.ts @@ -1,25 +1,25 @@ import { callerStack, Desc, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { REACTIVE, SubscriptionTarget } from "@starbeam/timeline"; +import { TAG, Tagged } from "@starbeam/timeline"; -export class DelegateInternalsImpl implements interfaces.DelegateCore { +export class DelegateInternalsImpl implements interfaces.DelegateTag { readonly type = "delegate"; constructor( readonly id: interfaces.ReactiveId, - readonly targets: readonly interfaces.SubscriptionTarget[], + readonly targets: readonly interfaces.Tagged[], readonly description: Description ) {} } export function DelegateInternals( - to: interfaces.SubscriptionTarget[] | interfaces.SubscriptionTarget, + to: interfaces.Tagged[] | interfaces.Tagged, options?: { description: string | Description } -): interfaces.DelegateCore { +): interfaces.DelegateTag { const desc = Desc( "delegate", options?.description ?? - (Array.isArray(to) ? undefined : SubscriptionTarget.description(to)) + (Array.isArray(to) ? undefined : Tagged.description(to)) ); return { @@ -34,7 +34,7 @@ export function Wrap( value: T, desc?: Description | string ): T & U { - Object.defineProperty(value, REACTIVE, { + Object.defineProperty(value, TAG, { configurable: true, writable: true, value: DelegateInternals(reactive, { @@ -59,15 +59,15 @@ export function Wrap( } function delegateDesc( - to: interfaces.SubscriptionTarget | interfaces.SubscriptionTarget[], + to: interfaces.Tagged | interfaces.Tagged[], desc?: string | Description ): Description { if (Array.isArray(to)) { return desc as Description; } else if (typeof desc === "string") { - return SubscriptionTarget.description(to).detail(desc); + return Tagged.description(to).detail(desc); } else if (desc === undefined) { - return SubscriptionTarget.description(to).detail("{delegate}"); + return Tagged.description(to).detail("{delegate}"); } else { return desc; } diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts index ecb2817b..cf44f4c8 100644 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/formula.ts @@ -5,8 +5,8 @@ import { } from "@starbeam/debug"; import type { Reactive, Stack } from "@starbeam/interfaces"; import type { UNINITIALIZED } from "@starbeam/shared"; -import { SubscriptionTarget } from "@starbeam/timeline"; -import { diff, Frame, REACTIVE, TIMELINE } from "@starbeam/timeline"; +import { Tagged } from "@starbeam/timeline"; +import { diff, Frame, TAG, TIMELINE } from "@starbeam/timeline"; export interface FormulaValidation { frame: Frame; @@ -30,13 +30,13 @@ export function FormulaValidation( const update = (caller: Stack): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(SubscriptionTarget.dependencies(frame)); + const oldDeps = new Set(Tagged.dependencies(frame)); frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(SubscriptionTarget.dependencies(frame)); + const newDeps = new Set(Tagged.dependencies(frame)); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { @@ -97,7 +97,7 @@ export function Formula( get: fn, }); - Object.defineProperty(fn, REACTIVE, { + Object.defineProperty(fn, TAG, { enumerable: false, configurable: true, writable: true, diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts index 2ad85bb3..95a931cd 100644 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts @@ -8,8 +8,8 @@ import type { UNINITIALIZED } from "@starbeam/shared"; import { diff, Frame, - REACTIVE, - SubscriptionTarget, + TAG, + Tagged, TIMELINE, } from "@starbeam/timeline"; @@ -48,12 +48,12 @@ export function PolledFormulaValidation( const update = (caller: Stack = callerStack()): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(SubscriptionTarget.dependencies(frame)); + const oldDeps = new Set(Tagged.dependencies(frame)); frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(SubscriptionTarget.dependencies(frame)); + const newDeps = new Set(Tagged.dependencies(frame)); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { @@ -103,7 +103,7 @@ export function PolledFormula( get: fn, }); - Object.defineProperty(fn, REACTIVE, { + Object.defineProperty(fn, TAG, { enumerable: false, configurable: true, writable: true, diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts index 2bb63814..9449a92d 100644 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ b/packages/universal/universal/src/reactive-core/marker.ts @@ -5,14 +5,14 @@ import { } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; import { - REACTIVE, - type SubscriptionTarget, + TAG, + type Tagged, TIMELINE, } from "@starbeam/timeline"; import { MutableInternals, type MutableInternalsImpl } from "../storage.js"; -export class ReactiveMarker implements SubscriptionTarget { +export class ReactiveMarker implements Tagged { static create(internals: MutableInternalsImpl): ReactiveMarker { return new ReactiveMarker(internals); } @@ -23,7 +23,7 @@ export class ReactiveMarker implements SubscriptionTarget { this.#internals = reactive; } - get [REACTIVE](): MutableInternals { + get [TAG](): MutableInternals { return this.#internals; } diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index 582c797c..4411ee99 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -1,5 +1,5 @@ import { Desc, type Description } from "@starbeam/debug"; -import type { ReactiveCore, ReactiveValue } from "@starbeam/interfaces"; +import type { ReactiveValue,Tag } from "@starbeam/interfaces"; import { Reactive as TimelineReactive } from "@starbeam/timeline"; import { isObject } from "@starbeam/verify"; @@ -34,7 +34,7 @@ export type IntoReactive = Reactive | T; export type TypedReactive< T, - I extends ReactiveCore = ReactiveCore + I extends Tag = Tag > = ReactiveValue; export type Reactive = TimelineReactive; diff --git a/packages/universal/universal/src/reactive-core/static.ts b/packages/universal/universal/src/reactive-core/static.ts index 1d71dbf8..fccd9d46 100644 --- a/packages/universal/universal/src/reactive-core/static.ts +++ b/packages/universal/universal/src/reactive-core/static.ts @@ -1,14 +1,14 @@ import type { Description } from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; -import { REACTIVE } from "@starbeam/shared"; +import { TAG } from "@starbeam/shared"; export function Static( value: T, description?: string | Description ): Reactive { return Object.freeze({ - [REACTIVE]: { + [TAG]: { type: "static", description: Desc("static", description), }, diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index a51058b4..aeeb3b37 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -5,10 +5,10 @@ import { descriptionFrom, DisplayStruct, } from "@starbeam/debug"; -import type { FormulaCore } from "@starbeam/interfaces"; +import type { FormulaTag } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import type { SubscriptionTarget } from "@starbeam/timeline"; -import { REACTIVE, TIMELINE } from "@starbeam/timeline"; +import type { Tagged } from "@starbeam/timeline"; +import { TAG, TIMELINE } from "@starbeam/timeline"; import { CompositeInternals } from "../storage.js"; import { Cell } from "./cell.js"; @@ -117,7 +117,7 @@ export class VariantGroup { } } -export class Variant implements SubscriptionTarget { +export class Variant implements Tagged { static selected( type: string, typeMarker: Marker, @@ -209,7 +209,7 @@ export class Variant implements SubscriptionTarget { value: T | UNINITIALIZED; }; readonly #value: Cell; - readonly [REACTIVE]: FormulaCore; + readonly [TAG]: FormulaTag; private constructor( type: string, @@ -217,14 +217,14 @@ export class Variant implements SubscriptionTarget { localTypeMarker: Marker, value: Cell, debug: { value: T | UNINITIALIZED }, - reactive: FormulaCore + reactive: FormulaTag ) { this.#type = type; this.#sharedTypeMarker = sharedTypeMarker; this.#localTypeMarker = localTypeMarker; this.#debug = debug; this.#value = value; - this[REACTIVE] = reactive; + this[TAG] = reactive; } get type(): string { @@ -289,7 +289,7 @@ export interface ReadonlyVariants { } export interface Variants - extends SubscriptionTarget { + extends Tagged { current: { [K in keyof Narrow]: K extends string ? Narrow[K] extends [] @@ -323,7 +323,7 @@ export interface Variants | undefined); } -class VariantsImpl implements SubscriptionTarget { +class VariantsImpl implements Tagged { static create( value: InternalVariant, description: Description @@ -361,7 +361,7 @@ class VariantsImpl implements SubscriptionTarget { this.#current = current; } - get [REACTIVE](): FormulaCore { + get [TAG](): FormulaTag { return CompositeInternals([this.#current], this.#description); } diff --git a/packages/universal/universal/src/storage.ts b/packages/universal/universal/src/storage.ts index e8efdab4..d5ed3f1a 100644 --- a/packages/universal/universal/src/storage.ts +++ b/packages/universal/universal/src/storage.ts @@ -1,11 +1,11 @@ import type { Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { SubscriptionTarget } from "@starbeam/timeline"; +import type { Tagged } from "@starbeam/timeline"; import { TIMELINE, type Timestamp } from "@starbeam/timeline"; export function StaticInternals( description: Description -): interfaces.StaticCore { +): interfaces.StaticTag { return { type: "static", description, @@ -14,11 +14,11 @@ export function StaticInternals( export function CompositeInternals( this: void, - children: SubscriptionTarget[], + children: Tagged[], description: Description -): interfaces.FormulaCore { +): interfaces.FormulaTag { return { - type: "composite", + type: "formula", description, children: () => { return children; @@ -28,9 +28,9 @@ export function CompositeInternals( export function DelegateInternals( this: void, - delegate: readonly SubscriptionTarget[], + delegate: readonly Tagged[], description: Description -): interfaces.DelegateCore { +): interfaces.DelegateTag { return { type: "delegate", description, @@ -38,7 +38,7 @@ export function DelegateInternals( }; } -export class MutableInternalsImpl implements interfaces.CellCore { +export class MutableInternalsImpl implements interfaces.CellTag { #frozen = false; #lastUpdated: Timestamp = TIMELINE.now; readonly type = "mutable"; @@ -73,4 +73,4 @@ export function MutableInternals( return new MutableInternalsImpl(description); } -export type MutableInternals = interfaces.CellCore; +export type MutableInternals = interfaces.CellTag; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index 997d510e..1ad19a7d 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,5 +1,5 @@ import { entryPointFn } from "@starbeam/debug"; -import { Frame, SubscriptionTarget } from "@starbeam/timeline"; +import { Frame, Tagged } from "@starbeam/timeline"; import { Cell, FormulaValidation, Reactive, Static } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; @@ -36,7 +36,7 @@ describe("reactive Factory", () => { const counter = Counter.create(); if (!import.meta.env.PROD) { - expect(SubscriptionTarget.description(counter).describe()).toBe( + expect(Tagged.description(counter).describe()).toBe( "Counter 0" ); } diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts index 1cd6574c..0819ff26 100644 --- a/packages/universal/universal/tests/setup.spec.ts +++ b/packages/universal/universal/tests/setup.spec.ts @@ -1,4 +1,4 @@ -import { SubscriptionTarget, TIMELINE } from "@starbeam/timeline"; +import { Tagged, TIMELINE } from "@starbeam/timeline"; import { Cell, Setup } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -129,11 +129,11 @@ describe("Setup", () => { cleanupCounter: 0, }); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); setup(); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -143,11 +143,11 @@ describe("Setup", () => { // cellB is not used in the initial setup, so it doesn't invalidate the setup cellB.set(20); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); setup(); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -157,8 +157,8 @@ describe("Setup", () => { cellA.set(1); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = SubscriptionTarget.lastUpdated(setup); + expect(Tagged.lastUpdated(setup)).toSatisfy(gt(ts)); + ts = Tagged.lastUpdated(setup); expect(variable).toEqual({ cell: 0, @@ -168,7 +168,7 @@ describe("Setup", () => { setup(); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 20, @@ -178,8 +178,8 @@ describe("Setup", () => { cellA.set(2); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = SubscriptionTarget.lastUpdated(setup); + expect(Tagged.lastUpdated(setup)).toSatisfy(gt(ts)); + ts = Tagged.lastUpdated(setup); expect(variable).toEqual({ cell: 20, @@ -189,7 +189,7 @@ describe("Setup", () => { setup(); - expect(SubscriptionTarget.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 2, diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index f6741815..94d576f5 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,4 +1,4 @@ -import { SubscriptionTarget } from "@starbeam/timeline"; +import { Tagged } from "@starbeam/timeline"; import { Formula, TIMELINE, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -195,7 +195,7 @@ describe("Variants", () => { // eslint-disable-next-line @typescript-eslint/no-inferrable-types const debug: boolean = false; -function Stability(reactive: SubscriptionTarget): { +function Stability(reactive: Tagged): { readonly changed: boolean; } { let changed = false; @@ -203,7 +203,7 @@ function Stability(reactive: SubscriptionTarget): { TIMELINE.on.change(reactive, (internals) => { if (debug) { console.group( - SubscriptionTarget.description(reactive).describe(), + Tagged.description(reactive).describe(), "invalidated by" ); console.log(internals.description.describe()); From 8287abe4e270edf66f1eee9336771f91eb55dfb6 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 23 Mar 2023 15:16:29 -0700 Subject: [PATCH 03/46] Created `@starbeam/tags` Previously, the implementation of tags lived in `TIMELINE`, which has a whole bunch of other unrelated stuff. So the abstraction went directly from the interfaces defined in `@starbeam/interfaces` to the full-fledged timeline definition in `@starbeam/timeline`. This created an awkward situation where tags ought to have been real objects (so they can share utility code), but we had utility function instead that worked with the interfaces to avoid dragging all of TIMELINE into the definition of tags. This commit separates tags into their own package which clearly defines the semantics of tags and provides concrete implementations for them. This simplifies the code considerably, and also more clearly communicates what tags are for. --- .vscode/settings.json | 7 +- packages/react/react/src/debug/warnings.ts | 4 +- packages/react/react/src/element.ts | 8 +- packages/universal/debug/index.ts | 11 +- .../universal/debug/src/description/impl.ts | 15 + packages/universal/debug/src/stack.ts | 2 +- packages/universal/debug/src/tag.ts | 45 +++ packages/universal/debug/src/timeline.ts | 4 +- packages/universal/interfaces/index.d.ts | 7 + .../universal/interfaces/src/description.d.ts | 6 + .../universal/interfaces/src/protocol.d.ts | 52 ++- .../universal/interfaces/src/timestamp.d.ts | 2 + packages/universal/js/src/collection.ts | 4 +- packages/universal/tags/.eslintrc.json | 12 + packages/universal/tags/.npmrc | 2 + packages/universal/tags/index.ts | 10 + packages/universal/tags/package.json | 27 ++ packages/universal/tags/rollup.config.mjs | 3 + packages/universal/tags/src/tag.ts | 209 +++++++++++ .../src/timeline => tags/src}/timestamp.ts | 11 +- packages/universal/tags/tsconfig.json | 12 + packages/universal/timeline/index.ts | 16 +- packages/universal/timeline/package.json | 1 + .../universal/timeline/src/timeline/frame.ts | 45 ++- .../universal/timeline/src/timeline/frames.ts | 10 +- .../timeline/src/timeline/protocol.ts | 330 ------------------ .../timeline/src/timeline/subscriptions.ts | 24 +- .../timeline/src/timeline/timeline.ts | 8 +- .../universal/timeline/src/utils/reactive.ts | 58 +++ .../universal/timeline/src/utils/tagged.ts | 107 ++++++ .../universal/timeline/src/utils/utils.ts | 2 + .../universal/timeline/tests/pollable.spec.ts | 30 +- .../universal/timeline/tests/protocol.spec.ts | 87 +++-- .../timeline/tests/support/mini-reactives.ts | 78 +---- packages/universal/universal/index.ts | 2 +- packages/universal/universal/package.json | 1 + .../universal/src/reactive-core/cell.ts | 34 +- .../universal/src/reactive-core/delegate.ts | 40 +-- .../src/reactive-core/formula/formula.ts | 13 +- .../reactive-core/formula/polled-formula.ts | 36 +- .../universal/src/reactive-core/marker.ts | 52 ++- .../universal/src/reactive-core/static.ts | 6 +- .../universal/src/reactive-core/variants.ts | 33 +- packages/universal/universal/src/storage.ts | 76 ---- .../universal/universal/tests/factory.spec.ts | 4 +- .../universal/universal/tests/setup.spec.ts | 22 +- .../universal/tests/variants.spec.ts | 4 +- .../x/devtool/src/single/single-reactive.tsx | 2 +- pnpm-lock.yaml | 17 + 49 files changed, 810 insertions(+), 781 deletions(-) create mode 100644 packages/universal/debug/src/tag.ts create mode 100644 packages/universal/tags/.eslintrc.json create mode 100644 packages/universal/tags/.npmrc create mode 100644 packages/universal/tags/index.ts create mode 100644 packages/universal/tags/package.json create mode 100644 packages/universal/tags/rollup.config.mjs create mode 100644 packages/universal/tags/src/tag.ts rename packages/universal/{timeline/src/timeline => tags/src}/timestamp.ts (87%) create mode 100644 packages/universal/tags/tsconfig.json delete mode 100644 packages/universal/timeline/src/timeline/protocol.ts create mode 100644 packages/universal/timeline/src/utils/reactive.ts create mode 100644 packages/universal/timeline/src/utils/tagged.ts create mode 100644 packages/universal/timeline/src/utils/utils.ts delete mode 100644 packages/universal/universal/src/storage.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 14bd9e8a..c405f48e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -76,10 +76,13 @@ }, "typescript.preferences.importModuleSpecifier": "project-relative", - "typescript.preferences.importModuleSpecifierEnding": "auto", + "typescript.preferences.importModuleSpecifierEnding": "js", "typescript.tsdk": "node_modules/typescript/lib", "typescript.tsserver.experimental.enableProjectDiagnostics": true, "vitest.enable": true, - "typescript.experimental.tsserver.web.enableProjectWideIntellisense": true + "typescript.experimental.tsserver.web.enableProjectWideIntellisense": true, + "rewrap.autoWrap.enabled": true, + "rewrap.reformat": true, + "rewrap.wrappingColumn": 80 } diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index 546e3083..40f02a15 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,5 +1,5 @@ import { Message } from "@starbeam/debug"; -import { Tagged, TIMELINE } from "@starbeam/timeline"; +import { TaggedUtils, TIMELINE } from "@starbeam/timeline"; import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; @@ -10,7 +10,7 @@ if (import.meta.env.DEV) { if (!WARNED) { WARNED = true; - const description = Tagged.description(reactive).userFacing; + const description = TaggedUtils.description(reactive).userFacing; const caller = stack.caller; const pad = Math.max( diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index fcd268b8..700475df 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,7 +1,6 @@ import type { browser } from "@domtree/flavors"; import { type DebugListener, Desc, type Description } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; -import type { Tagged } from "@starbeam/timeline"; +import type { Reactive, Tagged } from "@starbeam/interfaces"; import { type CleanupTarget, LIFETIME, @@ -201,10 +200,7 @@ export class ReactiveElement implements CleanupTarget { element.#lifecycle = Lifecycle.create(element.#description); } - static subscribe( - element: ReactiveElement, - reactive: Tagged - ): void { + static subscribe(element: ReactiveElement, reactive: Tagged): void { const subscription = TIMELINE.on.change(reactive, element.notify); element.on.cleanup(subscription); } diff --git a/packages/universal/debug/index.ts b/packages/universal/debug/index.ts index aeffe6d1..e8868b71 100644 --- a/packages/universal/debug/index.ts +++ b/packages/universal/debug/index.ts @@ -4,19 +4,19 @@ import { descriptionFrom } from "./src/stack.js"; export { Description, REUSE_ID } from "./src/description/impl.js"; export { - type DisplayStructOptions, DisplayStruct, + type DisplayStructOptions, } from "./src/inspect/display-struct.js"; export { - type Inspect, DEBUG, DEBUG_NAME, INSPECT, + type Inspect, inspect, inspector, } from "./src/inspect/inspect-support.js"; export { logged } from "./src/logged.js"; -export { type Logger, LOGGER, LogLevel } from "./src/logger.js"; +export { LOGGER, type Logger, LogLevel } from "./src/logger.js"; export { Block, Fragment, @@ -25,7 +25,7 @@ export { Styled, Styles, } from "./src/message.js"; -export { type DisplayParts, describeModule } from "./src/module.js"; +export { describeModule, type DisplayParts } from "./src/module.js"; export { callerStack, Desc, @@ -37,16 +37,17 @@ export { isErrorWithStack, Stack, } from "./src/stack.js"; +export { debugTag, logTag } from "./src/tag.js"; export { type CellConsumeOperation, type CellUpdateOperation, type DebugFilter, type DebugListener, type DebugOperation, + DebugTimeline, type Flush, type FrameConsumeOperation, type MutationLog, - DebugTimeline, } from "./src/timeline.js"; export { Tree } from "./src/tree.js"; export type { diff --git a/packages/universal/debug/src/description/impl.ts b/packages/universal/debug/src/description/impl.ts index b12d56dc..42d2b33d 100644 --- a/packages/universal/debug/src/description/impl.ts +++ b/packages/universal/debug/src/description/impl.ts @@ -258,6 +258,17 @@ if (import.meta.env.DEV) { ); } + forApi(api: string | interfaces.ApiDetails): interfaces.Description { + return new DebugDescription( + this.#id, + this.#type, + api, + this.#details, + this.#internal, + this.#stack + ); + } + #caller(options?: interfaces.DescriptionDescribeOptions): string { const caller = this.#stack?.caller; @@ -553,6 +564,10 @@ if (import.meta.env.DEV) { return !!(description && description instanceof ProdDescription); } + forApi(): interfaces.Description { + return this; + } + asImplementation(): interfaces.Description { return this; } diff --git a/packages/universal/debug/src/stack.ts b/packages/universal/debug/src/stack.ts index e1a58e08..7767dc3a 100644 --- a/packages/universal/debug/src/stack.ts +++ b/packages/universal/debug/src/stack.ts @@ -1,6 +1,6 @@ /// -import { type UnknownFn, getFirst } from "@starbeam/core-utils"; +import { getFirst, type UnknownFn } from "@starbeam/core-utils"; import type { DescriptionArgs, DescriptionDetails, diff --git a/packages/universal/debug/src/tag.ts b/packages/universal/debug/src/tag.ts new file mode 100644 index 00000000..a8866691 --- /dev/null +++ b/packages/universal/debug/src/tag.ts @@ -0,0 +1,45 @@ +import { isPresent } from "@starbeam/core-utils"; +import type { Tag } from "@starbeam/interfaces"; + +import { Tree } from "./tree.js"; + +export const debugTag = ( + tag: Tag, + { + implementation = false, + source = false, + id = false, + }: { implementation?: boolean; source?: boolean; id?: boolean } = {} +): string => { + const dependencies = [...tag.dependencies()]; + const descriptions = new Set( + dependencies.map((dependency) => { + return implementation + ? dependency.description + : dependency.description.userFacing; + }) + ); + + const nodes = [...descriptions] + .map((d) => { + const description = implementation ? d : d.userFacing; + return description.describe({ source, id }); + }) + .filter(isPresent); + + return Tree(...nodes).format(); +}; + +export const logTag = ( + tag: Tag, + options: { implementation?: boolean; source?: boolean; id?: boolean } = {} +): void => { + const debug = debugTag(tag, options); + + console.group( + tag.description.describe({ id: options.id }), + `(updated at ${tag.lastUpdated.toString({ format: "timestamp" })})` + ); + console.log(debug); + console.groupEnd(); +}; diff --git a/packages/universal/debug/src/timeline.ts b/packages/universal/debug/src/timeline.ts index 56e402b9..e8a29bbc 100644 --- a/packages/universal/debug/src/timeline.ts +++ b/packages/universal/debug/src/timeline.ts @@ -4,8 +4,8 @@ import type { FormulaTag, Frame, Stack, - Tagged, Tag, + Tagged, Timestamp, } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; @@ -139,7 +139,7 @@ function filterToPredicate( return (operation) => { if (operation.for === undefined) { return false; - } else if (operation.for.type === "mutable") { + } else if (operation.for.type === "cell") { // if the operation is for a dependency of the reactive we're // filtering by, then it's a match. return [...dependencies].includes(operation.for); diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 3b8c5962..8f8ad5f8 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -25,9 +25,14 @@ export type { ValidFrame, } from "./src/frame.js"; export type { + AbstractTag, CellTag, + DefaultMatcher, DelegateTag, + ExhaustiveMatcher, FormulaTag, + List, + Matcher, Reactive, ReactiveCell, ReactiveId, @@ -35,7 +40,9 @@ export type { StaticTag, Tag, Tagged, + TagMethods, TagType, + UpdateOptions, } from "./src/protocol.js"; export type { DisplayParts, diff --git a/packages/universal/interfaces/src/description.d.ts b/packages/universal/interfaces/src/description.d.ts index fd248c63..75404cdf 100644 --- a/packages/universal/interfaces/src/description.d.ts +++ b/packages/universal/interfaces/src/description.d.ts @@ -52,6 +52,12 @@ export interface Description extends DescriptionArgs { readonly userFacing: Description; readonly parts: DescriptionParts; + // TODO: Figure out how to reliably infer this in debug builds. Since people + // use a lot of different dev-time tools, it we may need to insert the + // information when we build the debug builds (it may not be possible to infer + // it from stack traces reliably).formula + forApi: (api: string | ApiDetails) => Description; + method: ( id: ReactiveId | symbol, name: string, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 4eb5a7ef..f2a1596b 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -6,19 +6,46 @@ import type { Timestamp } from "./timestamp.js"; export type ReactiveId = number | string | ReactiveId[]; -interface AbstractTag { - readonly type: string; +export interface AbstractTag { + readonly type: TagType; readonly description: Description; } +export type List = Iterable | readonly T[]; + +export class TagMethods { + readonly id: ReactiveId; + readonly lastUpdated: Timestamp; + readonly dependencies: () => List; + readonly description: Description; + match(matcher: Matcher): Tag; + subscriptionTargets(): List; +} + +export type ExhaustiveMatcher = { + [P in TagType]: (tag: Extract) => T; +}; + +export interface DefaultMatcher extends Partial> { + default: (internals: Tag) => T; +} + +export type Matcher = ExhaustiveMatcher | DefaultMatcher; + +export interface UpdateOptions { + readonly stack: Stack; + readonly timeline: { bump: (tag: CellTag, caller: Stack) => Timestamp }; +} + /** * Cell is the fundamental mutable reactive value. All subscriptions in Starbeam are ultimately * subscriptions to cells, and all mutations in Starbeam are ultimately mutations to cells. */ -export interface CellTag extends AbstractTag { - readonly type: "mutable"; +export interface CellTag extends AbstractTag, TagMethods { + readonly type: "cell"; readonly lastUpdated: Timestamp; isFrozen?: () => boolean; + update: (options: UpdateOptions) => void; } /** @@ -33,9 +60,9 @@ export interface CellTag extends AbstractTag { * notified of a change to the composite's children, it removes subscriptions from any stale * dependencies and adds subscriptions to any new dependencies. */ -export interface FormulaTag extends AbstractTag { +export interface FormulaTag extends AbstractTag, TagMethods { readonly type: "formula"; - children: () => Tagged[]; + children: () => readonly Tagged[]; } /** @@ -47,7 +74,7 @@ export interface FormulaTag extends AbstractTag { * targets. This means that delegates don't need to know when their value changes, and don't need to * notify the timeline when their targets change. */ -export interface DelegateTag extends AbstractTag { +export interface DelegateTag extends AbstractTag, TagMethods { readonly type: "delegate"; readonly targets: readonly Tagged[]; } @@ -64,10 +91,19 @@ export interface DelegateTag extends AbstractTag { * TODO: Do we need a separate fundamental type for pollable formulas, which can get new * dependencies even if they never invalidate? */ -export interface StaticTag extends AbstractTag { +export interface StaticTag extends AbstractTag, TagMethods { readonly type: "static"; } +/** + * A tag validates a reactive value. The behavior of a tags is defined in relation to reads and + * writes of the reactive value they represent. Tags model **value composition** (and functional + * composition), not a more general algebra. + * + * In other words, it doesn't make sense to think about the composition of tags abstracted from the + * values they represent. Attempting to think about tags this way makes them seem more general than + * they are, and that generality breaks system invariants derived from value composition. + */ export type Tag = CellTag | FormulaTag | DelegateTag | StaticTag; export type TagType = Tag["type"]; diff --git a/packages/universal/interfaces/src/timestamp.d.ts b/packages/universal/interfaces/src/timestamp.d.ts index 97b6abc7..559905d0 100644 --- a/packages/universal/interfaces/src/timestamp.d.ts +++ b/packages/universal/interfaces/src/timestamp.d.ts @@ -3,6 +3,8 @@ export interface Timestamp { eq: (other: Timestamp) => boolean; next: () => Timestamp; + + toString: (options?: { format?: "timestamp" }) => string; } export interface TimestampStatics { diff --git a/packages/universal/js/src/collection.ts b/packages/universal/js/src/collection.ts index f63baf27..31a1fcb0 100644 --- a/packages/universal/js/src/collection.ts +++ b/packages/universal/js/src/collection.ts @@ -1,5 +1,5 @@ import type { Description, Stack } from "@starbeam/debug"; -import { Tagged } from "@starbeam/timeline"; +import { TaggedUtils } from "@starbeam/timeline"; import { Cell, Marker } from "@starbeam/universal"; import { expected, isPresent, verified } from "@starbeam/verify"; @@ -203,7 +203,7 @@ export class Collection { } let item: Item; - const iteration = Tagged.description(this.#iteration); + const iteration = TaggedUtils.description(this.#iteration); if (disposition === "miss") { item = Item.uninitialized(iteration, member, caller); diff --git a/packages/universal/tags/.eslintrc.json b/packages/universal/tags/.eslintrc.json new file mode 100644 index 00000000..697af1bd --- /dev/null +++ b/packages/universal/tags/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/commonjs"], + "files": ["index.ts", "src/**/*.ts"], + "parserOptions": { + "project": "packages/universal/tags/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/tags/.npmrc b/packages/universal/tags/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/tags/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/tags/index.ts b/packages/universal/tags/index.ts new file mode 100644 index 00000000..5f5f6117 --- /dev/null +++ b/packages/universal/tags/index.ts @@ -0,0 +1,10 @@ +export { CellTag, DelegateTag, FormulaTag, StaticTag, Tag } from "./src/tag.js"; +export { + debug as debugTimestamp, + getNow, + max, + NOW, + type Now, + Timestamp, + zero, +} from "./src/timestamp.js"; diff --git a/packages/universal/tags/package.json b/packages/universal/tags/package.json new file mode 100644 index 00000000..04c451f9 --- /dev/null +++ b/packages/universal/tags/package.json @@ -0,0 +1,27 @@ +{ + "name": "@starbeam/tags", + "types": "index.ts", + "publishConfig": { + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.cjs" + } + }, + "main": "dist/index.cjs", + "types": "dist/index.d.ts" + }, + "starbeam:type": "library:public", + "scripts": { + "test:types": "tsc -b" + }, + "dependencies": { + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/shared": "workspace:^" + }, + "devDependencies": { + "@starbeam-dev/build-support": "workspace:*" + } +} diff --git a/packages/universal/tags/rollup.config.mjs b/packages/universal/tags/rollup.config.mjs new file mode 100644 index 00000000..dc01dc49 --- /dev/null +++ b/packages/universal/tags/rollup.config.mjs @@ -0,0 +1,3 @@ +import { Package } from "@starbeam-dev/build-support"; + +export default Package.config(import.meta); diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts new file mode 100644 index 00000000..75c896eb --- /dev/null +++ b/packages/universal/tags/src/tag.ts @@ -0,0 +1,209 @@ +import type { Description, UpdateOptions } from "@starbeam/interfaces"; +import type * as interfaces from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; + +import { type Timestamp, zero } from "./timestamp.js"; +import { NOW } from "./timestamp.js"; + +export abstract class Tag + implements interfaces.AbstractTag, interfaces.TagMethods +{ + static lastUpdatedIn( + this: void, + tags: interfaces.List + ): Timestamp { + let lastUpdatedTimestamp = zero(); + + for (const child of Tag.dependenciesInList(tags)) { + if (child.lastUpdated.gt(lastUpdatedTimestamp)) { + lastUpdatedTimestamp = child.lastUpdated; + } + } + + return lastUpdatedTimestamp; + } + + static *dependenciesInList( + this: void, + children: interfaces.List + ): Iterable { + for (const child of children) { + yield* child.dependencies(); + } + } + + abstract readonly type: interfaces.TagType; + readonly #description: Description; + constructor(description: Description) { + this.#description = description; + } + + get id(): interfaces.ReactiveId { + return this.#description.id; + } + + match(matcher: interfaces.Matcher): T { + const fn = matcher[this.type]; + if (typeof fn === "function") { + return fn(this as never); + } + + return (matcher as interfaces.DefaultMatcher).default( + this as interfaces.Tag + ); + } + + abstract readonly lastUpdated: Timestamp; + + abstract dependencies(): interfaces.List; + + get description(): Description { + return this.#description; + } + + /** + * By default, a tag yields itself when asked for subsbcription target. The + * delegate tag overrides this behavior. + */ + *subscriptionTargets(): interfaces.List { + yield this as interfaces.Tag; + } +} + +export class CellTag extends Tag implements interfaces.CellTag { + static create(description: Description, lastUpdated = NOW.bump()): CellTag { + return new CellTag(description, lastUpdated); + } + + readonly type = "cell"; + + #frozen = false; + #lastUpdated: Timestamp; + + private constructor(description: Description, lastUpdated: Timestamp) { + super(description); + this.#lastUpdated = lastUpdated; + } + + isFrozen() { + return this.#frozen; + } + + freeze() { + this.#frozen = true; + } + + get lastUpdated(): Timestamp { + return this.#lastUpdated; + } + + set lastUpdated(timestamp: Timestamp) { + this.#lastUpdated = timestamp; + } + + override *dependencies(): interfaces.List { + if (!this.#frozen) yield this; + } + + update({ timeline, stack }: UpdateOptions): void { + if (this.#frozen) { + throw TypeError("Cannot update frozen object"); + } + + this.#lastUpdated = timeline.bump(this, stack); + } +} + +export class StaticTag extends Tag implements interfaces.StaticTag { + static create(description: Description): StaticTag { + return new StaticTag(description); + } + + readonly type = "static"; + + override readonly lastUpdated = NOW.now; + + override *dependencies(): interfaces.List { + /** static tags have no dependencies */ + } +} + +export class FormulaTag extends Tag implements interfaces.FormulaTag { + static create( + description: Description, + children: () => interfaces.List + ): FormulaTag { + return new FormulaTag(description, children); + } + + readonly type = "formula"; + readonly #children: () => interfaces.List; + + private constructor( + description: Description, + children: () => interfaces.List + ) { + super(description); + this.#children = children; + } + + children(): readonly interfaces.Tagged[] { + return [...this.#children()]; + } + + override get lastUpdated(): interfaces.Timestamp { + let lastUpdatedTimestamp = zero(); + + for (const child of this.dependencies()) { + if (child.lastUpdated.gt(lastUpdatedTimestamp)) { + lastUpdatedTimestamp = child.lastUpdated; + } + } + + return lastUpdatedTimestamp; + } + + override *dependencies(): interfaces.List { + yield* Tag.dependenciesInList(this.children().map((child) => child[TAG])); + } +} + +export class DelegateTag extends Tag implements interfaces.DelegateTag { + static create( + description: Description, + targets: readonly interfaces.Tagged[] + ): DelegateTag { + return new DelegateTag(description, targets); + } + + readonly type = "delegate"; + readonly #targets: readonly interfaces.Tagged[]; + + private constructor( + description: Description, + targets: readonly interfaces.Tagged[] + ) { + super(description); + this.#targets = targets; + } + + get targets(): readonly interfaces.Tagged[] { + return this.#targets; + } + + override *subscriptionTargets(): interfaces.List { + for (const target of this.#targets) { + yield* target[TAG].subscriptionTargets(); + } + } + + override *dependencies(): interfaces.List { + for (const target of this.#targets) { + yield* target[TAG].dependencies(); + } + } + + override get lastUpdated(): Timestamp { + return Tag.lastUpdatedIn(this.subscriptionTargets()); + } +} diff --git a/packages/universal/timeline/src/timeline/timestamp.ts b/packages/universal/tags/src/timestamp.ts similarity index 87% rename from packages/universal/timeline/src/timeline/timestamp.ts rename to packages/universal/tags/src/timestamp.ts index 73721156..85eb53f8 100644 --- a/packages/universal/timeline/src/timeline/timestamp.ts +++ b/packages/universal/tags/src/timestamp.ts @@ -30,7 +30,7 @@ export class TimestampImpl implements interfaces.Timestamp { } } - static debug(timestamp: interfaces.Timestamp): { at: number } { + static debug(this: void, timestamp: interfaces.Timestamp): { at: number } { TimestampImpl.assert(timestamp, "Timestamp.debug"); return { at: timestamp.#timestamp }; } @@ -66,8 +66,12 @@ export class TimestampImpl implements interfaces.Timestamp { return new Timestamp(peerBump()); } - toString = (): string => { - return `#`; + toString = (options: { format?: "timestamp" } = {}): string => { + if (options?.format === "timestamp") { + return String(this.#timestamp); + } else { + return `#`; + } }; } @@ -101,3 +105,4 @@ export class Now { } export const NOW = new Now(); +export const debug = Timestamp.debug; diff --git a/packages/universal/tags/tsconfig.json b/packages/universal/tags/tsconfig.json new file mode 100644 index 00000000..4790a1ab --- /dev/null +++ b/packages/universal/tags/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../dist/types", + "declarationMap": true, + "outDir": "../../../dist/packages", + "types": ["../../env"] + }, + "exclude": ["dist/**/*"] +} diff --git a/packages/universal/timeline/index.ts b/packages/universal/timeline/index.ts index de54f50c..83432a17 100644 --- a/packages/universal/timeline/index.ts +++ b/packages/universal/timeline/index.ts @@ -1,4 +1,3 @@ -// FIXME: Move the core of this to @starbeam/shared export { type ComponentContext, CONTEXT, @@ -17,23 +16,16 @@ export { Frame, type FrameValidation, } from "./src/timeline/frame.js"; -export { - Reactive, - Tag as ReactiveInternals, - Tagged as Tagged, -} from "./src/timeline/protocol.js"; export { type NotifyReady, Subscriptions, } from "./src/timeline/subscriptions.js"; -export { INSPECT } from "./src/timeline/timestamp.js"; -export { max, getNow as now, zero } from "./src/timeline/timestamp.js"; export { diff } from "./src/timeline/utils.js"; +export { Reactive, TaggedUtils } from "./src/utils/utils.js"; +export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; import type * as interfaces from "@starbeam/interfaces"; +export type { interfaces }; -import * as timestamp from "./src/timeline/timestamp.js"; - -export const Timestamp = timestamp.Timestamp; -export type Timestamp = interfaces.Timestamp; +export { Timestamp } from "@starbeam/tags"; diff --git a/packages/universal/timeline/package.json b/packages/universal/timeline/package.json index 750d4aee..5d4391a7 100644 --- a/packages/universal/timeline/package.json +++ b/packages/universal/timeline/package.json @@ -29,6 +29,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/verify": "workspace:^" }, "devDependencies": { diff --git a/packages/universal/timeline/src/timeline/frame.ts b/packages/universal/timeline/src/timeline/frame.ts index 23210834..9ba76732 100644 --- a/packages/universal/timeline/src/timeline/frame.ts +++ b/packages/universal/timeline/src/timeline/frame.ts @@ -1,18 +1,18 @@ import type { - CellTag, Description, - FormulaTag, Frame as IFrame, + Tagged, Timestamp, } from "@starbeam/interfaces"; +import type * as interfaces from "@starbeam/interfaces"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; +import { CellTag, FormulaTag, getNow } from "@starbeam/tags"; import { isNotEqual, verified } from "@starbeam/verify"; +import { TaggedUtils } from "../utils/utils.js"; import type { FrameStack } from "./frames.js"; import { getID } from "./id.js"; -import { Tagged } from "./protocol.js"; import type { Timeline } from "./timeline.js"; -import { getNow } from "./timestamp.js"; interface Marker { [TAG]: Omit & { @@ -20,7 +20,9 @@ interface Marker { }; } -export class Frame implements Tagged, IFrame { +export class Frame + implements Tagged, IFrame +{ static create( this: void, value: T, @@ -33,13 +35,10 @@ export class Frame implements Tagged, IFrame { return new Frame( value, { - [TAG]: { - type: "mutable", - lastUpdated: finalized, - description: description - .key("initialized?", { id }) - .asImplementation(), - }, + [TAG]: CellTag.create( + description.key("initialized?", { id }).asImplementation(), + finalized + ), }, children, finalized, @@ -56,11 +55,10 @@ export class Frame implements Tagged, IFrame { return new Frame( UNINITIALIZED, { - [TAG]: { - type: "mutable", - lastUpdated: finalized, - description: description.detail("initialized?", { id }), - }, + [TAG]: CellTag.create( + description.detail("initialized?", { id }), + finalized + ), }, new Set(), finalized, @@ -119,13 +117,10 @@ export class Frame implements Tagged, IFrame { } get [TAG](): FormulaTag { - return { - type: "formula", - description: this.#description, - children: (): Tagged[] => { - return [this.#initialized, ...this.#children]; - }, - }; + return FormulaTag.create(this.#description, () => [ + this.#initialized, + ...this.#children, + ]); } get description(): Description { @@ -161,7 +156,7 @@ export class Frame implements Tagged, IFrame { validate(): FrameValidation> { if ( this.#value === UNINITIALIZED || - Tagged.lastUpdatedIn([...this.#children]).gt(this.#finalized) + TaggedUtils.lastUpdatedIn([...this.#children]).gt(this.#finalized) ) { return { status: "invalid" }; } else { diff --git a/packages/universal/timeline/src/timeline/frames.ts b/packages/universal/timeline/src/timeline/frames.ts index e251476c..a7b3b683 100644 --- a/packages/universal/timeline/src/timeline/frames.ts +++ b/packages/universal/timeline/src/timeline/frames.ts @@ -1,10 +1,10 @@ import type { DebugTimeline, Stack } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { CellTag } from "@starbeam/interfaces"; +import type { CellTag, Tagged } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; +import { TaggedUtils } from "../utils/utils.js"; import { ActiveFrame, type Frame } from "./frame.js"; -import { Tagged } from "./protocol.js"; import type { Subscriptions } from "./subscriptions.js"; import type { Timeline } from "./timeline.js"; @@ -96,12 +96,12 @@ export class FrameStack { frame.add(reactive); return; } else { - const delegatesTo = Tagged.subscriptionTargets(reactive).filter((r) => - Tagged.is(r, "mutable") + const delegatesTo = TaggedUtils.subscriptionTargets(reactive).filter( + (r) => TaggedUtils.is(r, "cell") ); for (const target of delegatesTo) { - if (Tagged.is(target, "mutable")) { + if (TaggedUtils.is(target, "cell")) { this.#timeline.untrackedRead(target, caller); } } diff --git a/packages/universal/timeline/src/timeline/protocol.ts b/packages/universal/timeline/src/timeline/protocol.ts deleted file mode 100644 index 77233fb9..00000000 --- a/packages/universal/timeline/src/timeline/protocol.ts +++ /dev/null @@ -1,330 +0,0 @@ -import type * as Debug from "@starbeam/debug"; -import { Desc, Tree } from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; -import { isPresent } from "@starbeam/verify"; - -import { Timestamp, zero } from "./timestamp.js"; - -export type Reactive = interfaces.Reactive; - -type ExhaustiveMatcher = { - [P in interfaces.TagType]: (tag: Extract) => T; -}; - -export type Tag = interfaces.Tag; - -interface DefaultMatcher extends Partial> { - default: (internals: Tag) => T; -} - -type Matcher = ExhaustiveMatcher | DefaultMatcher; - -export type Tagged = - interfaces.Tagged; - -export const Tagged = { - description(this: void, reactive: Tagged): Debug.Description { - return Tag.description(reactive[TAG]); - }, - - id(this: void, reactive: Tagged): interfaces.ReactiveId { - return Tag.id(reactive[TAG]); - }, - - is( - this: void, - reactive: Tagged, - kind: T - ): reactive is { - [TAG]: Extract; - } { - return Tag.is(reactive[TAG], kind); - }, - - match(this: void, reactive: Tagged, matcher: Matcher): T { - return Tag.match(reactive[TAG], matcher); - }, - - /** - * This method returns a list of reactives that subscribers to the original reactive should - * actually subscribe to. - * - * Normally, this is just the reactive itself. However, if a ReactiveProtocol is a delegate, - * subscribers can subscribe directly to the delegate's targets. - * - * This is because a delegate's targets can't change, so it's safe to subscribe directly to the - * targets. - * - * This makes it possible to create abstractions around reactive values that don't have to worry - * about manually updating their subscribers when their values change. - */ - subscriptionTargets(this: void, reactive: Tagged): Tagged[] { - const internals = reactive[TAG]; - - console.log({ internals }); - if (internals.type === "delegate") { - return internals.targets.flatMap(Tagged.subscriptionTargets); - } else { - return [reactive]; - } - }, - - dependencies(this: void, reactive: Tagged): Iterable { - return Tag.dependencies(reactive[TAG]); - }, - - *dependenciesInList( - this: void, - children: readonly Tagged[] - ): Iterable { - for (const child of children) { - yield* Tag.dependencies(child[TAG]); - } - }, - - lastUpdated(this: void, reactive: Tagged): Timestamp { - return Tag.lastUpdated(reactive[TAG]); - }, - - lastUpdatedIn(this: void, reactives: Tagged[]): Timestamp { - let lastUpdatedTimestamp = zero(); - - for (const child of Tagged.dependenciesInList(reactives)) { - if (child.lastUpdated.gt(lastUpdatedTimestamp)) { - lastUpdatedTimestamp = child.lastUpdated; - } - } - - return lastUpdatedTimestamp; - }, - - log( - this: void, - reactive: Tagged, - options: { implementation?: boolean; source?: boolean; id?: boolean } = {} - ): void { - Tag.log(reactive[TAG], options); - }, - - debug( - this: void, - reactive: Tagged, - { - implementation = false, - source = false, - }: { implementation?: boolean; source?: boolean } = {} - ): string { - return Tag.debug(reactive[TAG], { - implementation, - source, - }); - }, -} as const; - -export const Tag = { - is( - this: void, - internals: interfaces.Tag, - kind: T - ): internals is Extract { - return internals.type === kind; - }, - - id(this: void, internals: interfaces.Tag): interfaces.ReactiveId { - return internals.description.id; - }, - - /** - * Return a flat list of the mutable reactives that this reactive depends on. - * - * This list is only valid until the next time anyone reads from the reactive. It's intended to be - * used along with code that updates the dependencies whenever the reactive is read. - */ - *dependencies(internals: interfaces.Tag): Iterable { - switch (internals.type) { - case "static": - return; - case "mutable": - if (internals.isFrozen?.()) { - break; - } - - yield internals; - break; - case "delegate": - for (const target of Tag.subscribesTo(internals)) { - yield* Tag.dependencies(target); - } - break; - case "formula": - yield* Tagged.dependenciesInList(internals.children()); - break; - } - }, - - *dependenciesInList( - this: void, - children: readonly interfaces.Tag[] - ): Iterable { - for (const child of children) { - yield* Tag.dependencies(child); - } - }, - - subscribesTo(this: void, internals: interfaces.Tag): interfaces.Tag[] { - if (internals.type === "delegate") { - return internals.targets.flatMap((protocol) => - Tagged.subscriptionTargets(protocol).map((p) => p[TAG]) - ); - } else { - return [internals]; - } - }, - - lastUpdated(this: void, internals: interfaces.Tag): Timestamp { - switch (internals.type) { - case "static": - return zero(); - case "mutable": - return internals.lastUpdated; - case "delegate": { - const delegates = Tag.subscribesTo(internals); - return Tag.lastUpdatedIn(delegates); - } - case "formula": { - let lastUpdatedTimestamp = zero(); - - for (const child of Tag.dependencies(internals)) { - if (child.lastUpdated.gt(lastUpdatedTimestamp)) { - lastUpdatedTimestamp = child.lastUpdated; - } - } - - return lastUpdatedTimestamp; - } - } - }, - - lastUpdatedIn(this: void, core: Tag[]): Timestamp { - let lastUpdatedTimestamp = zero(); - - for (const child of Tag.dependenciesInList(core)) { - if (child.lastUpdated.gt(lastUpdatedTimestamp)) { - lastUpdatedTimestamp = child.lastUpdated; - } - } - - return lastUpdatedTimestamp; - }, - - description(this: void, core: Tag): Debug.Description { - return core.description; - }, - - debug( - this: void, - internals: Tag, - { - implementation = false, - source = false, - id = false, - }: { implementation?: boolean; source?: boolean; id?: boolean } = {} - ): string { - const dependencies = [...Tag.dependencies(internals)]; - const descriptions = new Set( - dependencies.map((dependency) => { - return implementation - ? dependency.description - : dependency.description.userFacing; - }) - ); - - const nodes = [...descriptions] - .map((d) => { - const description = implementation ? d : d.userFacing; - return description.describe({ source, id }); - }) - .filter(isPresent); - - return Tree(...nodes).format(); - }, - - log( - this: void, - internals: interfaces.Tag, - options: { implementation?: boolean; source?: boolean; id?: boolean } = {} - ): void { - const debug = Tag.debug(internals, options); - - console.group( - Tag.description(internals).describe({ id: options.id }), - `(updated at ${Timestamp.debug(Tag.lastUpdated(internals)).at})` - ); - console.log(debug); - console.groupEnd(); - }, - - match(this: void, internals: interfaces.Tag, matcher: Matcher): T { - const fn = matcher[internals.type]; - if (typeof fn === "function") { - return fn(internals as never); - } - - return (matcher as DefaultMatcher).default(internals); - }, -}; - -function is( - this: void, - value: T | interfaces.Reactive -): value is interfaces.Reactive { - return !!( - value && - (typeof value === "object" || typeof value === "function") && - TAG in value - ); -} - -export const Reactive = { - is(this: void, value: unknown): value is interfaces.Reactive { - return is(value) && hasRead(value); - }, - - from( - this: void, - value: T | Reactive, - description?: string | Debug.Description - ): Reactive { - if (Reactive.is(value)) { - return value; - } else { - return new Static(value, Desc("static", description)); - } - }, -}; - -function hasRead(value: object): value is { read: () => T } { - return "read" in value && typeof value.read === "function"; -} - -class Static implements interfaces.ReactiveValue { - readonly #value: T; - readonly [TAG]: interfaces.StaticTag; - - constructor(value: T, description: Debug.Description) { - this.#value = value; - this[TAG] = { - type: "static", - description, - }; - } - - get current(): T { - return this.#value; - } - - read(): T { - return this.#value; - } -} diff --git a/packages/universal/timeline/src/timeline/subscriptions.ts b/packages/universal/timeline/src/timeline/subscriptions.ts index d9585b00..e26f06c9 100644 --- a/packages/universal/timeline/src/timeline/subscriptions.ts +++ b/packages/universal/timeline/src/timeline/subscriptions.ts @@ -1,7 +1,7 @@ -import type { CellTag, Diff, FormulaTag } from "@starbeam/interfaces"; +import type { CellTag, Diff, FormulaTag, Tagged } from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; -import { Tagged } from "./protocol.js"; +import { TaggedUtils } from "../utils/utils.js"; import { diff } from "./utils.js"; export type NotifyReady = (internals: CellTag) => void; @@ -43,7 +43,7 @@ export class Subscriptions { return new Subscriptions(); } - readonly #formulaMap = FormulaMap.empty(); + readonly #formulaMap = SubscriberMap.empty(); readonly #cellMap = CellMap.empty(); /** @@ -70,11 +70,11 @@ export class Subscriptions { * different dependencies. */ register(target: Tagged, ready: NotifyReady): Unsubscribe { - const subscriptionTargets = Tagged.subscriptionTargets(target); + const subscriptionTargets = TaggedUtils.subscriptionTargets(target); const unsubscribes = subscriptionTargets.map((t) => { const entry = this.#formulaMap.register(t); - for (const dependency of Tagged.dependencies(t)) { + for (const dependency of TaggedUtils.dependencies(t)) { this.#cellMap.register(dependency, entry); } @@ -110,11 +110,11 @@ export class Subscriptions { } /** - * A mapping from reactives (basically formulas) to their subscriptions. + * A mapping from tagged values to their subscriptions. */ -class FormulaMap { - static empty(): FormulaMap { - return new FormulaMap(); +class SubscriberMap { + static empty(): SubscriberMap { + return new SubscriberMap(); } readonly #mapping = new WeakMap(); @@ -130,7 +130,7 @@ class FormulaMap { const entry = ReactiveSubscription.create(frame); this.#mapping.set(frame, entry); return { - add: new Set(Tagged.dependencies(frame)), + add: new Set(TaggedUtils.dependencies(frame)), remove: new Set(), entry, }; @@ -151,7 +151,7 @@ class FormulaMap { class ReactiveSubscription { static create(target: Tagged): ReactiveSubscription { - const deps = new Set(Tagged.dependencies(target)); + const deps = new Set(TaggedUtils.dependencies(target)); return new ReactiveSubscription(deps); } @@ -175,7 +175,7 @@ class ReactiveSubscription { update(frame: Tagged): Diff { const prev = this.#deps; - const next = new Set(Tagged.dependencies(frame)); + const next = new Set(TaggedUtils.dependencies(frame)); this.#deps = next; return diff(prev, next); diff --git a/packages/universal/timeline/src/timeline/timeline.ts b/packages/universal/timeline/src/timeline/timeline.ts index 907b5d53..4e16c57b 100644 --- a/packages/universal/timeline/src/timeline/timeline.ts +++ b/packages/universal/timeline/src/timeline/timeline.ts @@ -1,13 +1,13 @@ import type { Stack } from "@starbeam/debug"; import { DebugTimeline } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { CellTag } from "@starbeam/interfaces"; +import type { CellTag, Tagged } from "@starbeam/interfaces"; +import { getNow, NOW } from "@starbeam/tags"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; +import { TaggedUtils } from "../utils/utils.js"; import { FrameStack } from "./frames.js"; -import { Tagged } from "./protocol.js"; import { type NotifyReady, Subscriptions } from "./subscriptions.js"; -import { getNow, NOW } from "./timestamp.js"; type TimelineOp = "consumed" | "bumped" | "evaluating" | "initial"; @@ -85,7 +85,7 @@ export class Timeline { get #debug(): DebugTimeline { if (!this.#debugTimeline) { - this.#debugTimeline = DebugTimeline.create({ now: getNow }, Tagged); + this.#debugTimeline = DebugTimeline.create({ now: getNow }, TaggedUtils); } return this.#debugTimeline; diff --git a/packages/universal/timeline/src/utils/reactive.ts b/packages/universal/timeline/src/utils/reactive.ts new file mode 100644 index 00000000..bb8e4fc1 --- /dev/null +++ b/packages/universal/timeline/src/utils/reactive.ts @@ -0,0 +1,58 @@ +import type * as Debug from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; +import type * as interfaces from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { StaticTag } from "@starbeam/tags"; + +export type Reactive = interfaces.Reactive; + +function is( + this: void, + value: T | interfaces.Reactive +): value is interfaces.Reactive { + return !!( + value && + (typeof value === "object" || typeof value === "function") && + TAG in value + ); +} + +export const Reactive = { + is(this: void, value: unknown): value is interfaces.Reactive { + return is(value) && hasRead(value); + }, + + from( + this: void, + value: T | Reactive, + description?: string | Debug.Description + ): Reactive { + if (Reactive.is(value)) { + return value; + } else { + return new Static(value, Desc("static", description)); + } + }, +}; + +function hasRead(value: object): value is { read: () => T } { + return "read" in value && typeof value.read === "function"; +} + +class Static implements interfaces.ReactiveValue { + readonly #value: T; + readonly [TAG]: interfaces.StaticTag; + + constructor(value: T, description: Debug.Description) { + this.#value = value; + this[TAG] = StaticTag.create(description); + } + + get current(): T { + return this.#value; + } + + read(): T { + return this.#value; + } +} diff --git a/packages/universal/timeline/src/utils/tagged.ts b/packages/universal/timeline/src/utils/tagged.ts new file mode 100644 index 00000000..75cf8407 --- /dev/null +++ b/packages/universal/timeline/src/utils/tagged.ts @@ -0,0 +1,107 @@ +import type * as Debug from "@starbeam/debug"; +import { debugTag, logTag } from "@starbeam/debug"; +import type * as interfaces from "@starbeam/interfaces"; +import type { Matcher, Tag } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { type Timestamp, zero } from "@starbeam/tags"; + +export type Tagged = + interfaces.Tagged; + +export const TaggedUtils = new (class { + description(this: void, reactive: Tagged): Debug.Description { + return reactive[TAG].description; + } + + id(this: void, reactive: Tagged): interfaces.ReactiveId { + return reactive[TAG].id; + } + + is( + this: void, + reactive: Tagged, + kind: T + ): reactive is { + [TAG]: Extract; + } { + return reactive[TAG].type === kind; + } + + match(this: void, reactive: Tagged, matcher: Matcher): T { + return reactive[TAG].match(matcher) as T; + } + + /** + * This method returns a list of reactives that subscribers to the original reactive should + * actually subscribe to. + * + * Normally, this is just the reactive itself. However, if a ReactiveProtocol is a delegate, + * subscribers can subscribe directly to the delegate's targets. + * + * This is because a delegate's targets can't change, so it's safe to subscribe directly to the + * targets. + * + * This makes it possible to create abstractions around reactive values that don't have to worry + * about manually updating their subscribers when their values change. + */ + subscriptionTargets(this: void, reactive: Tagged): Tagged[] { + const tag = reactive[TAG]; + + if (tag.type === "delegate") { + return tag.targets.flatMap(TaggedUtils.subscriptionTargets); + } else { + return [reactive]; + } + } + + dependencies(this: void, reactive: Tagged): Iterable { + return reactive[TAG].dependencies(); + } + + *dependenciesInList( + this: void, + children: readonly Tagged[] + ): Iterable { + for (const child of children) { + yield* child[TAG].dependencies(); + } + } + + lastUpdated(this: void, reactive: Tagged): Timestamp { + return reactive[TAG].lastUpdated; + } + + lastUpdatedIn(this: void, reactives: Tagged[]): Timestamp { + let lastUpdatedTimestamp = zero(); + + for (const child of TaggedUtils.dependenciesInList(reactives)) { + if (child.lastUpdated.gt(lastUpdatedTimestamp)) { + lastUpdatedTimestamp = child.lastUpdated; + } + } + + return lastUpdatedTimestamp; + } + + log( + this: void, + reactive: Tagged, + options: { implementation?: boolean; source?: boolean; id?: boolean } = {} + ): void { + logTag(reactive[TAG], options); + } + + debug( + this: void, + reactive: Tagged, + { + implementation = false, + source = false, + }: { implementation?: boolean; source?: boolean } = {} + ): string { + return debugTag(reactive[TAG], { + implementation, + source, + }); + } +})(); diff --git a/packages/universal/timeline/src/utils/utils.ts b/packages/universal/timeline/src/utils/utils.ts new file mode 100644 index 00000000..382e100f --- /dev/null +++ b/packages/universal/timeline/src/utils/utils.ts @@ -0,0 +1,2 @@ +export { Reactive } from "./reactive.js"; +export { TaggedUtils } from "./tagged.js"; diff --git a/packages/universal/timeline/tests/pollable.spec.ts b/packages/universal/timeline/tests/pollable.spec.ts index aff441fe..20686e7c 100644 --- a/packages/universal/timeline/tests/pollable.spec.ts +++ b/packages/universal/timeline/tests/pollable.spec.ts @@ -1,6 +1,7 @@ import { isPresentArray } from "@starbeam/core-utils"; -import { descriptionFrom } from "@starbeam/debug"; +import { Desc, descriptionFrom } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; +import { DelegateTag } from "@starbeam/tags"; import { Frame, TAG, TIMELINE } from "@starbeam/timeline"; import { describe, expect, test } from "vitest"; @@ -62,14 +63,7 @@ describe("pollable", () => { const delegate: ReactiveValue = { read: () => cell.current, - [TAG]: { - type: "delegate", - description: descriptionFrom({ - type: "delegate", - api: "delegate", - }), - targets: [cell], - }, + [TAG]: DelegateTag.create(Desc("delegate"), [cell]), }; let stale = false; @@ -93,14 +87,7 @@ describe("pollable", () => { const delegate: ReactiveValue = { read: () => sum.read(), - [TAG]: { - type: "delegate", - description: descriptionFrom({ - type: "delegate", - api: "delegate", - }), - targets: [sum], - }, + [TAG]: DelegateTag.create(Desc("delegate"), [sum]), }; let stale = false; @@ -160,14 +147,7 @@ function Sum(): { ) ); }, - [TAG]: { - type: "delegate", - description: descriptionFrom({ - type: "delegate", - api: "delegate", - }), - targets: [frame], - }, + [TAG]: DelegateTag.create(Desc("delegate"), [frame]), }; return { sum, numbers }; diff --git a/packages/universal/timeline/tests/protocol.spec.ts b/packages/universal/timeline/tests/protocol.spec.ts index 6d415c3b..86e6ce64 100644 --- a/packages/universal/timeline/tests/protocol.spec.ts +++ b/packages/universal/timeline/tests/protocol.spec.ts @@ -1,6 +1,7 @@ -import { callerStack, descriptionFrom } from "@starbeam/debug"; -import type { FormulaTag } from "@starbeam/interfaces"; -import { TAG, Tagged, TIMELINE, zero } from "@starbeam/timeline"; +import { callerStack, Desc } from "@starbeam/debug"; +import type { Tagged } from "@starbeam/interfaces"; +import { CellTag, FormulaTag, zero } from "@starbeam/tags"; +import { TAG, TaggedUtils, TIMELINE } from "@starbeam/timeline"; import { beforeAll, describe, expect, it } from "vitest"; import { Cell, FreezableCell, Static } from "./support/mini-reactives.js"; @@ -9,31 +10,21 @@ describe("Tagged", () => { beforeAll(() => { // make sure the timeline is not at 0, which would make a comparison with TIMELINE.now sometimes // equivalent to Timestamp.zero(), and we want to test the difference. - TIMELINE.bump( - { - type: "mutable", - description: descriptionFrom({ - type: "cell", - api: "Cell", - }), - lastUpdated: zero(), - }, - callerStack(-1) - ); + TIMELINE.bump(CellTag.create(Desc("cell"), zero()), callerStack(-1)); }); describe("Static", () => { it("has the zero timestamp for lastUpdated", () => { const tom = Static("Tom Dale"); - expect(String(Tagged.lastUpdated(tom))).toBe(String(zero())); - expect(String(Tagged.lastUpdatedIn([tom]))).toBe(String(zero())); + expect(String(TaggedUtils.lastUpdated(tom))).toBe(String(zero())); + expect(String(TaggedUtils.lastUpdatedIn([tom]))).toBe(String(zero())); }); it("has no dependencies", () => { const tom = Static("Tom Dale"); - expect([...Tagged.dependencies(tom)]).toEqual([]); - expect([...Tagged.dependenciesInList([tom])]).toEqual([]); + expect([...TaggedUtils.dependencies(tom)]).toEqual([]); + expect([...TaggedUtils.dependenciesInList([tom])]).toEqual([]); }); }); @@ -41,26 +32,34 @@ describe("Tagged", () => { it("has the current timestamp for lastUpdated", () => { const original = TIMELINE.now; const tom = Cell("Tom"); - expect(String(Tagged.lastUpdated(tom))).toBe(String(TIMELINE.now)); + expect(String(TaggedUtils.lastUpdated(tom))).toBe(String(TIMELINE.now)); const nullvox = Cell("nullvox"); const nullvoxTimestamp = TIMELINE.now; - expect(String(Tagged.lastUpdated(nullvox))).toBe( - String(nullvoxTimestamp) - ); - expect(String(Tagged.lastUpdatedIn([tom, nullvox]))).toBe( - String(TIMELINE.now) - ); + expect( + String(TaggedUtils.lastUpdated(nullvox)), + "lastUpdated(nullvox)" + ).toBe(String(nullvoxTimestamp)); + expect( + String(TaggedUtils.lastUpdatedIn([tom, nullvox])), + "lastUpdatedIn([tom,nullvox])" + ).toBe(String(TIMELINE.now)); expect(String(TIMELINE.now)).not.toBe(String(original)); + console.log("reading", TIMELINE.now); + tom.read(); + console.log("writing", TIMELINE.now); tom.current = "Tom Dale"; - expect(String(TIMELINE.now)).not.toBe(String(original)); - expect(String(Tagged.lastUpdated(tom))).toBe(String(TIMELINE.now)); - expect(String(Tagged.lastUpdated(nullvox))).toBe( + console.log("wrote", TIMELINE.now); + expect(String(TIMELINE.now), "TIMELINE.now").not.toBe(String(original)); + expect(String(TaggedUtils.lastUpdated(tom)), "lastUpdated(tom)").toBe( + String(TIMELINE.now) + ); + expect(String(TaggedUtils.lastUpdated(nullvox))).toBe( String(nullvoxTimestamp) ); - expect(String(Tagged.lastUpdatedIn([tom, nullvox]))).toBe( + expect(String(TaggedUtils.lastUpdatedIn([tom, nullvox]))).toBe( String(TIMELINE.now) ); }); @@ -69,8 +68,8 @@ describe("Tagged", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - expect([...Tagged.dependencies(tom)]).toEqual([tom[TAG]]); - expect([...Tagged.dependenciesInList([tom, nullvox])]).toEqual([ + expect([...TaggedUtils.dependencies(tom)]).toEqual([tom[TAG]]); + expect([...TaggedUtils.dependenciesInList([tom, nullvox])]).toEqual([ tom[TAG], nullvox[TAG], ]); @@ -83,8 +82,8 @@ describe("Tagged", () => { nullvox.current = "@nullvoxpopuli"; - expect([...Tagged.dependencies(tom)]).toEqual([]); - expect([...Tagged.dependenciesInList([tom, nullvox])]).toEqual([ + expect([...TaggedUtils.dependencies(tom)]).toEqual([]); + expect([...TaggedUtils.dependenciesInList([tom, nullvox])]).toEqual([ nullvox[TAG], ]); }); @@ -95,28 +94,22 @@ describe("Tagged", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - const composite: FormulaTag = { - type: "formula", - description: descriptionFrom({ - type: "formula", - api: "Composite", - }), - children() { - return [tom, nullvox]; - }, - }; + const formula = FormulaTag.create(Desc("formula"), () => [tom, nullvox]); const Both: Tagged = { - [TAG]: composite, + [TAG]: formula, }; - expect(String(Tagged.lastUpdated(Both))).toBe(String(TIMELINE.now)); + expect(String(TaggedUtils.lastUpdated(Both))).toBe(String(TIMELINE.now)); - expect([...Tagged.dependencies(Both)]).toEqual([tom[TAG], nullvox[TAG]]); + expect([...TaggedUtils.dependencies(Both)]).toEqual([ + tom[TAG], + nullvox[TAG], + ]); tom.current = "Tom Dale"; - expect(String(Tagged.lastUpdated(Both))).toBe(String(TIMELINE.now)); + expect(String(TaggedUtils.lastUpdated(Both))).toBe(String(TIMELINE.now)); }); }); }); diff --git a/packages/universal/timeline/tests/support/mini-reactives.ts b/packages/universal/timeline/tests/support/mini-reactives.ts index 4645edc0..15c0450a 100644 --- a/packages/universal/timeline/tests/support/mini-reactives.ts +++ b/packages/universal/timeline/tests/support/mini-reactives.ts @@ -4,14 +4,10 @@ import { descriptionFrom, type Stack, } from "@starbeam/debug"; -import type { - CellTag, - ReactiveCell, - ReactiveValue, -} from "@starbeam/interfaces"; +import type { ReactiveCell, ReactiveValue, Tagged } from "@starbeam/interfaces"; import { TAG, type UNINITIALIZED } from "@starbeam/shared"; -import { type Tagged } from "@starbeam/timeline"; -import { diff, Frame, TIMELINE, type Timestamp } from "@starbeam/timeline"; +import { CellTag, StaticTag } from "@starbeam/tags"; +import { diff, Frame, TIMELINE } from "@starbeam/timeline"; export interface FreezableCell extends ReactiveCell { freeze: () => void; @@ -22,22 +18,13 @@ export type Cell = ReactiveCell; class CellImpl implements ReactiveCell { readonly [TAG]: CellTag; #value: T; - #lastUpdated: Timestamp; - constructor(value: T, timestamp: Timestamp) { - const lastUpdated = (): Timestamp => this.#lastUpdated; - - this[TAG] = { - type: "mutable", - description: Desc("cell"), - get lastUpdated(): Timestamp { - return lastUpdated(); - }, - }; + + constructor(value: T) { + this[TAG] = CellTag.create(Desc("cell")); this.#value = value; - this.#lastUpdated = timestamp; } - read(caller: Stack): T { + read(caller = callerStack()): T { TIMELINE.didConsumeCell(this, caller); return this.#value; } @@ -47,32 +34,21 @@ class CellImpl implements ReactiveCell { set current(newValue: T) { this.#value = newValue; - this.#lastUpdated = TIMELINE.bump(this[TAG], callerStack()); + this[TAG].lastUpdated = TIMELINE.bump(this[TAG], callerStack()); } } export function Cell(value: T): CellImpl { - return new CellImpl(value, TIMELINE.next()); + return new CellImpl(value); } class FreezableCellImpl implements ReactiveCell { readonly [TAG]: CellTag; - #isFrozen = false; #value: T; - #lastUpdated: Timestamp; - constructor(value: T, timestamp: Timestamp) { - const lastUpdated = (): Timestamp => this.#lastUpdated; - - this[TAG] = { - type: "mutable", - description: Desc("cell"), - get lastUpdated(): Timestamp { - return lastUpdated(); - }, - isFrozen: () => this.#isFrozen, - }; + constructor(value: T) { + this[TAG] = CellTag.create(Desc("cell")); + this.#value = value; - this.#lastUpdated = timestamp; } read(caller: Stack): T { @@ -85,27 +61,21 @@ class FreezableCellImpl implements ReactiveCell { set current(newValue: T) { this.#value = newValue; - this.#lastUpdated = TIMELINE.bump(this[TAG], callerStack()); + TIMELINE.bump(this[TAG], callerStack()); } freeze(): void { - this.#isFrozen = true; + this[TAG].freeze(); } } export function FreezableCell(value: T): FreezableCellImpl { - return new FreezableCellImpl(value, TIMELINE.next()); + return new FreezableCellImpl(value); } export function Static(value: T): ReactiveValue { return { - [TAG]: { - type: "static", - description: descriptionFrom({ - api: "Static", - type: "static", - }), - }, + [TAG]: StaticTag.create(Desc("static")), read() { return value; }, @@ -149,24 +119,14 @@ export function Marker(): { instance: Tagged; update: () => void; } { - let lastUpdated = TIMELINE.next(); - const internals: CellTag = { - type: "mutable", - description: descriptionFrom({ - type: "cell", - api: "Marker", - }), - get lastUpdated() { - return lastUpdated; - }, - }; + const tag = CellTag.create(Desc("cell")); return { instance: { - [TAG]: internals, + [TAG]: tag, }, update: () => { - lastUpdated = TIMELINE.bump(internals, callerStack()); + TIMELINE.bump(tag, callerStack()); }, }; } diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 2cd6a56d..b5716227 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -5,7 +5,7 @@ export { CustomBlueprint, CustomBuilder, } from "./src/reactive-core/custom.js"; -export { DelegateInternals, Wrap } from "./src/reactive-core/delegate.js"; +export { Wrap } from "./src/reactive-core/delegate.js"; export { Formula, FormulaValidation, diff --git a/packages/universal/universal/package.json b/packages/universal/universal/package.json index 6154fbe1..75740267 100644 --- a/packages/universal/universal/package.json +++ b/packages/universal/universal/package.json @@ -29,6 +29,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/timeline": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/universal/universal/src/reactive-core/cell.ts b/packages/universal/universal/src/reactive-core/cell.ts index 6d5b7194..5afd96a2 100644 --- a/packages/universal/universal/src/reactive-core/cell.ts +++ b/packages/universal/universal/src/reactive-core/cell.ts @@ -9,10 +9,8 @@ import { import type * as interfaces from "@starbeam/interfaces"; import type { ReactiveValue } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import { INSPECT, TAG, TIMELINE } from "@starbeam/timeline"; - -import type { MutableInternalsImpl } from "../storage.js"; -import { MutableInternals } from "../storage.js"; +import { CellTag } from "@starbeam/tags"; +import { TAG, TIMELINE } from "@starbeam/timeline"; export interface CellPolicy { equals: (a: T, b: T) => boolean; @@ -21,33 +19,31 @@ export interface CellPolicy { export type Equality = (a: T, b: T) => boolean; +const INSPECT = Symbol.for("nodejs.util.inspect.custom"); + export class ReactiveCell implements ReactiveValue { static create( value: T, - internals: MutableInternalsImpl, + tag: CellTag, equals: Equality = Object.is ): ReactiveCell { - return new ReactiveCell(value, equals, internals); + return new ReactiveCell(value, equals, tag); } #value: T; - readonly #internals: MutableInternalsImpl; + readonly #tag: CellTag; readonly #equals: Equality; declare [INSPECT]: () => object; - private constructor( - value: T, - equals: Equality, - reactive: MutableInternalsImpl - ) { + private constructor(value: T, equals: Equality, tag: CellTag) { this.#value = value; this.#equals = equals; - this.#internals = reactive; + this.#tag = tag; if (import.meta.env.DEV) { this[INSPECT] = (): object => { - const { description, lastUpdated } = this.#internals; + const { description, lastUpdated } = this.#tag; const desc = ` (${description.describe()})`; @@ -67,7 +63,7 @@ export class ReactiveCell implements ReactiveValue { } freeze(): void { - this.#internals.freeze(); + this.#tag.freeze(); } get current(): T { @@ -109,12 +105,12 @@ export class ReactiveCell implements ReactiveValue { } this.#value = value; - this.#internals.update(caller); + this.#tag.update({ timeline: TIMELINE, stack: caller }); return true; } - get [TAG](): MutableInternals { - return this.#internals; + get [TAG](): CellTag { + return this.#tag; } } @@ -146,7 +142,7 @@ export function Cell( equals = description.equals ?? Object.is; } - return ReactiveCell.create(value, MutableInternals(desc), equals); + return ReactiveCell.create(value, CellTag.create(desc), equals); } const CALLER_FRAME = 1; diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/universal/src/reactive-core/delegate.ts index ed59975c..d732962c 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/universal/src/reactive-core/delegate.ts @@ -1,33 +1,7 @@ -import { callerStack, Desc, type Description } from "@starbeam/debug"; +import { callerStack, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { TAG, Tagged } from "@starbeam/timeline"; - -export class DelegateInternalsImpl implements interfaces.DelegateTag { - readonly type = "delegate"; - - constructor( - readonly id: interfaces.ReactiveId, - readonly targets: readonly interfaces.Tagged[], - readonly description: Description - ) {} -} - -export function DelegateInternals( - to: interfaces.Tagged[] | interfaces.Tagged, - options?: { description: string | Description } -): interfaces.DelegateTag { - const desc = Desc( - "delegate", - options?.description ?? - (Array.isArray(to) ? undefined : Tagged.description(to)) - ); - - return { - type: "delegate", - description: desc, - targets: Array.isArray(to) ? to : [to], - }; -} +import { DelegateTag } from "@starbeam/tags"; +import { TAG, TaggedUtils } from "@starbeam/timeline"; export function Wrap( reactive: U, @@ -37,9 +11,7 @@ export function Wrap( Object.defineProperty(value, TAG, { configurable: true, writable: true, - value: DelegateInternals(reactive, { - description: delegateDesc(reactive, desc), - }), + value: DelegateTag.create(delegateDesc(reactive, desc), [reactive]), }); Object.defineProperty(value, "read", { @@ -65,9 +37,9 @@ function delegateDesc( if (Array.isArray(to)) { return desc as Description; } else if (typeof desc === "string") { - return Tagged.description(to).detail(desc); + return TaggedUtils.description(to).detail(desc); } else if (desc === undefined) { - return Tagged.description(to).detail("{delegate}"); + return TaggedUtils.description(to).detail("{delegate}"); } else { return desc; } diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts index cf44f4c8..7e28a467 100644 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/formula.ts @@ -5,7 +5,8 @@ import { } from "@starbeam/debug"; import type { Reactive, Stack } from "@starbeam/interfaces"; import type { UNINITIALIZED } from "@starbeam/shared"; -import { Tagged } from "@starbeam/timeline"; +import { DelegateTag } from "@starbeam/tags"; +import { TaggedUtils } from "@starbeam/timeline"; import { diff, Frame, TAG, TIMELINE } from "@starbeam/timeline"; export interface FormulaValidation { @@ -30,13 +31,13 @@ export function FormulaValidation( const update = (caller: Stack): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(Tagged.dependencies(frame)); + const oldDeps = new Set(TaggedUtils.dependencies(frame)); frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(Tagged.dependencies(frame)); + const newDeps = new Set(TaggedUtils.dependencies(frame)); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { @@ -101,11 +102,7 @@ export function Formula( enumerable: false, configurable: true, writable: true, - value: { - type: "delegate", - description: desc, - targets: [formula.frame], - }, + value: DelegateTag.create(desc, [formula.frame]), }); Object.defineProperty(fn, Symbol.for("nodejs.util.inspect.custom"), { diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts index 95a931cd..2d7376fa 100644 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts @@ -1,17 +1,13 @@ import { callerStack, + Desc, type Description, descriptionFrom, } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; import type { UNINITIALIZED } from "@starbeam/shared"; -import { - diff, - Frame, - TAG, - Tagged, - TIMELINE, -} from "@starbeam/timeline"; +import { DelegateTag } from "@starbeam/tags"; +import { diff, Frame, TAG, TaggedUtils, TIMELINE } from "@starbeam/timeline"; import type { Formula } from "./formula.js"; @@ -48,12 +44,12 @@ export function PolledFormulaValidation( const update = (caller: Stack = callerStack()): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(Tagged.dependencies(frame)); + const oldDeps = new Set(TaggedUtils.dependencies(frame)); frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(Tagged.dependencies(frame)); + const newDeps = new Set(TaggedUtils.dependencies(frame)); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { @@ -76,17 +72,11 @@ export function PolledFormula( callback: () => T, description?: Description | string ): Formula { - const formula = PolledFormulaValidation( - callback, - descriptionFrom({ - type: "formula", - api: { - package: "@starbeam/universal", - name: "PolledFormula", - }, - fromUser: description, - }) - ); + const desc = Desc("formula", description).forApi({ + package: "@starbeam/universal", + name: "PolledFormula", + }); + const formula = PolledFormulaValidation(callback, desc); const fn = (): T => Frame.value(formula.poll()); @@ -107,11 +97,7 @@ export function PolledFormula( enumerable: false, configurable: true, writable: true, - value: { - type: "delegate", - description, - targets: [formula.frame], - }, + value: DelegateTag.create(desc, [formula.frame]), }); return fn as Formula; diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts index 9449a92d..42344b8b 100644 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ b/packages/universal/universal/src/reactive-core/marker.ts @@ -1,34 +1,26 @@ -import { - callerStack, - type Description, - descriptionFrom, -} from "@starbeam/debug"; -import type { Stack } from "@starbeam/interfaces"; -import { - TAG, - type Tagged, - TIMELINE, -} from "@starbeam/timeline"; - -import { MutableInternals, type MutableInternalsImpl } from "../storage.js"; - -export class ReactiveMarker implements Tagged { - static create(internals: MutableInternalsImpl): ReactiveMarker { - return new ReactiveMarker(internals); +import { callerStack, Desc, type Description } from "@starbeam/debug"; +import type { Stack, Tagged } from "@starbeam/interfaces"; +import type * as interfaces from "@starbeam/interfaces"; +import { CellTag } from "@starbeam/tags"; +import { TAG, TIMELINE } from "@starbeam/timeline"; + +export class ReactiveMarker implements Tagged { + static create(tag: CellTag): ReactiveMarker { + return new ReactiveMarker(tag); } - readonly #internals: MutableInternalsImpl; + readonly #tag: CellTag; - private constructor(reactive: MutableInternalsImpl) { - this.#internals = reactive; + private constructor(tag: CellTag) { + this.#tag = tag; } - get [TAG](): MutableInternals { - return this.#internals; + get [TAG](): CellTag { + return this.#tag; } freeze(): void { - this.#internals.freeze(); + this.#tag.freeze(); } consume(caller = callerStack()): void { @@ -36,20 +28,16 @@ export class ReactiveMarker implements Tagged { } update(caller: Stack): void { - this.#internals.update(caller); + this.#tag.update({ timeline: TIMELINE, stack: caller }); } } export function Marker(description?: string | Description): ReactiveMarker { return ReactiveMarker.create( - MutableInternals( - descriptionFrom({ - type: "cell", - api: { - package: "@starbeam/universal", - name: "Marker", - }, - fromUser: description, + CellTag.create( + Desc("cell", description).forApi({ + package: "@starbeam/universal", + name: "Marker", }) ) ); diff --git a/packages/universal/universal/src/reactive-core/static.ts b/packages/universal/universal/src/reactive-core/static.ts index fccd9d46..d37029cd 100644 --- a/packages/universal/universal/src/reactive-core/static.ts +++ b/packages/universal/universal/src/reactive-core/static.ts @@ -2,16 +2,14 @@ import type { Description } from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; +import { StaticTag } from "@starbeam/tags"; export function Static( value: T, description?: string | Description ): Reactive { return Object.freeze({ - [TAG]: { - type: "static", - description: Desc("static", description), - }, + [TAG]: StaticTag.create(Desc("static", description)), current: value, read: () => value, }); diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index aeeb3b37..88cf0466 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -5,12 +5,12 @@ import { descriptionFrom, DisplayStruct, } from "@starbeam/debug"; -import type { FormulaTag } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; +import { FormulaTag } from "@starbeam/tags"; +import { DelegateTag } from "@starbeam/tags"; import type { Tagged } from "@starbeam/timeline"; import { TAG, TIMELINE } from "@starbeam/timeline"; -import { CompositeInternals } from "../storage.js"; import { Cell } from "./cell.js"; import { Marker } from "./marker.js"; @@ -117,7 +117,7 @@ export class VariantGroup { } } -export class Variant implements Tagged { +export class Variant implements Tagged { static selected( type: string, typeMarker: Marker, @@ -140,11 +140,11 @@ export class Variant implements Tagged { localTypeMarker, val, { value }, - CompositeInternals( - [val, localTypeMarker], + DelegateTag.create( description.implementation("selected", { reason: `selected`, - }) + }), + [val, localTypeMarker] ) ); } @@ -167,9 +167,9 @@ export class Variant implements Tagged { val, { value: UNINITIALIZED }, - CompositeInternals( - [val, localTypeMarker], - description.implementation("selected", { reason: "selected" }) + DelegateTag.create( + description.implementation("selected", { reason: "selected" }), + [val, localTypeMarker] ) ) as Variant; } @@ -209,7 +209,7 @@ export class Variant implements Tagged { value: T | UNINITIALIZED; }; readonly #value: Cell; - readonly [TAG]: FormulaTag; + readonly [TAG]: DelegateTag; private constructor( type: string, @@ -217,7 +217,7 @@ export class Variant implements Tagged { localTypeMarker: Marker, value: Cell, debug: { value: T | UNINITIALIZED }, - reactive: FormulaTag + reactive: DelegateTag ) { this.#type = type; this.#sharedTypeMarker = sharedTypeMarker; @@ -288,8 +288,7 @@ export interface ReadonlyVariants { ) => this is Omit & ReadonlyVariants; } -export interface Variants - extends Tagged { +export interface Variants extends Tagged { current: { [K in keyof Narrow]: K extends string ? Narrow[K] extends [] @@ -346,6 +345,7 @@ class VariantsImpl implements Tagged { readonly #typeMarker: Marker; readonly #groups: VariantGroups; readonly #description: Description; + readonly [TAG]: FormulaTag; #current: Variant; private constructor( @@ -359,11 +359,12 @@ class VariantsImpl implements Tagged { this.#groups = VariantGroups.empty(description); this.#description = description; this.#current = current; + this[TAG] = FormulaTag.create(description, () => [this.#current]); } - get [TAG](): FormulaTag { - return CompositeInternals([this.#current], this.#description); - } + // get [TAG](): FormulaTag { + // return CompositeInternals([this.#current], this.#description); + // } get current(): Variant { return this.#current; diff --git a/packages/universal/universal/src/storage.ts b/packages/universal/universal/src/storage.ts deleted file mode 100644 index d5ed3f1a..00000000 --- a/packages/universal/universal/src/storage.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { Description } from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; -import type { Tagged } from "@starbeam/timeline"; -import { TIMELINE, type Timestamp } from "@starbeam/timeline"; - -export function StaticInternals( - description: Description -): interfaces.StaticTag { - return { - type: "static", - description, - }; -} - -export function CompositeInternals( - this: void, - children: Tagged[], - description: Description -): interfaces.FormulaTag { - return { - type: "formula", - description, - children: () => { - return children; - }, - }; -} - -export function DelegateInternals( - this: void, - delegate: readonly Tagged[], - description: Description -): interfaces.DelegateTag { - return { - type: "delegate", - description, - targets: [...delegate], - }; -} - -export class MutableInternalsImpl implements interfaces.CellTag { - #frozen = false; - #lastUpdated: Timestamp = TIMELINE.now; - readonly type = "mutable"; - - constructor(readonly description: Description) {} - - get lastUpdated(): Timestamp { - return this.#lastUpdated; - } - - isFrozen(): boolean { - return this.#frozen; - } - - freeze(): void { - this.#frozen = true; - } - - update(caller: interfaces.Stack): void { - if (this.#frozen) { - throw TypeError("Cannot update frozen object"); - } - - this.#lastUpdated = TIMELINE.bump(this, caller); - } -} - -export function MutableInternals( - this: void, - description: Description -): MutableInternalsImpl { - return new MutableInternalsImpl(description); -} - -export type MutableInternals = interfaces.CellTag; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index 1ad19a7d..b6d8da00 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,5 +1,5 @@ import { entryPointFn } from "@starbeam/debug"; -import { Frame, Tagged } from "@starbeam/timeline"; +import { Frame, TaggedUtils } from "@starbeam/timeline"; import { Cell, FormulaValidation, Reactive, Static } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; @@ -36,7 +36,7 @@ describe("reactive Factory", () => { const counter = Counter.create(); if (!import.meta.env.PROD) { - expect(Tagged.description(counter).describe()).toBe( + expect(TaggedUtils.description(counter).describe()).toBe( "Counter 0" ); } diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts index 0819ff26..da5551c8 100644 --- a/packages/universal/universal/tests/setup.spec.ts +++ b/packages/universal/universal/tests/setup.spec.ts @@ -1,4 +1,4 @@ -import { Tagged, TIMELINE } from "@starbeam/timeline"; +import { TaggedUtils, TIMELINE } from "@starbeam/timeline"; import { Cell, Setup } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -129,11 +129,11 @@ describe("Setup", () => { cleanupCounter: 0, }); - expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); setup(); - expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -143,11 +143,11 @@ describe("Setup", () => { // cellB is not used in the initial setup, so it doesn't invalidate the setup cellB.set(20); - expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); setup(); - expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -157,8 +157,8 @@ describe("Setup", () => { cellA.set(1); - expect(Tagged.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = Tagged.lastUpdated(setup); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(gt(ts)); + ts = TaggedUtils.lastUpdated(setup); expect(variable).toEqual({ cell: 0, @@ -168,7 +168,7 @@ describe("Setup", () => { setup(); - expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 20, @@ -178,8 +178,8 @@ describe("Setup", () => { cellA.set(2); - expect(Tagged.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = Tagged.lastUpdated(setup); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(gt(ts)); + ts = TaggedUtils.lastUpdated(setup); expect(variable).toEqual({ cell: 20, @@ -189,7 +189,7 @@ describe("Setup", () => { setup(); - expect(Tagged.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 2, diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 94d576f5..2d2dd081 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,4 +1,4 @@ -import { Tagged } from "@starbeam/timeline"; +import { type Tagged, TaggedUtils } from "@starbeam/timeline"; import { Formula, TIMELINE, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -203,7 +203,7 @@ function Stability(reactive: Tagged): { TIMELINE.on.change(reactive, (internals) => { if (debug) { console.group( - Tagged.description(reactive).describe(), + TaggedUtils.description(reactive).describe(), "invalidated by" ); console.log(internals.description.describe()); diff --git a/packages/x/devtool/src/single/single-reactive.tsx b/packages/x/devtool/src/single/single-reactive.tsx index 5c468276..38e24888 100644 --- a/packages/x/devtool/src/single/single-reactive.tsx +++ b/packages/x/devtool/src/single/single-reactive.tsx @@ -23,7 +23,7 @@ export function DevtoolsFor(props: { .map((operation) => operation.for) .filter( (value): value is MutableInternals => - value !== undefined && value.type === "mutable" + value !== undefined && value.type === "cell" ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d437b1d..c2d2c13f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -773,6 +773,19 @@ importers: dependencies: '@starbeam/shared': link:.. + packages/universal/tags: + specifiers: + '@starbeam-dev/build-support': workspace:* + '@starbeam/debug': workspace:^ + '@starbeam/interfaces': workspace:^ + '@starbeam/shared': workspace:^ + dependencies: + '@starbeam/debug': link:../debug + '@starbeam/interfaces': link:../interfaces + '@starbeam/shared': link:../shared + devDependencies: + '@starbeam-dev/build-support': link:../../../workspace/build + packages/universal/test-utils: specifiers: '@starbeam-dev/build-support': workspace:* @@ -793,12 +806,14 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ '@starbeam/shared': workspace:^ + '@starbeam/tags': workspace:^ '@starbeam/verify': workspace:^ dependencies: '@starbeam/core-utils': link:../core-utils '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces '@starbeam/shared': link:../shared + '@starbeam/tags': link:../tags '@starbeam/verify': link:../verify devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build @@ -822,6 +837,7 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ '@starbeam/shared': workspace:^ + '@starbeam/tags': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/verify': workspace:^ dependencies: @@ -829,6 +845,7 @@ importers: '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces '@starbeam/shared': link:../shared + '@starbeam/tags': link:../tags '@starbeam/timeline': link:../timeline '@starbeam/verify': link:../verify devDependencies: From c24194c2f3c2341c6593e5c23399a4c1625d574e Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 23 Mar 2023 15:53:12 -0700 Subject: [PATCH 04/46] WIP --- packages/universal/interfaces/index.d.ts | 1 + .../universal/interfaces/src/protocol.d.ts | 18 ++++++- packages/universal/tags/index.ts | 1 + packages/universal/tags/src/tagged.ts | 6 +++ .../universal/timeline/src/timeline/frame.ts | 6 +-- .../universal/timeline/src/timeline/frames.ts | 8 ++- .../timeline/src/timeline/subscriptions.ts | 29 ++++++---- .../timeline/src/timeline/timeline.ts | 10 ++-- .../universal/timeline/src/utils/tagged.ts | 53 +++++-------------- .../universal/src/reactive-core/cell.ts | 19 +++---- .../universal/src/reactive-core/marker.ts | 16 +++--- 11 files changed, 87 insertions(+), 80 deletions(-) create mode 100644 packages/universal/tags/src/tagged.ts diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 8f8ad5f8..87724ca5 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -37,6 +37,7 @@ export type { ReactiveCell, ReactiveId, ReactiveValue, + SpecificTag, StaticTag, Tag, Tagged, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index f2a1596b..ffa5b146 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -106,9 +106,25 @@ export interface StaticTag extends AbstractTag, TagMethods { */ export type Tag = CellTag | FormulaTag | DelegateTag | StaticTag; export type TagType = Tag["type"]; +export type SpecificTag = Extract; +/** + * A `Tagged` object is a reactive object that has a `Tag` (which is used to + * validate it). + * + * NOTE: In previous versions of Starbeam, it was legal to change the tag after + * the tagged object was initially created. However, this made it impossible to + * use an tagged object's tag as a key in a WeakMap, which meant that the tagged + * object itself had to be passed around even when it was semantically + * unimportant. + * + * These days, the `[TAG]` property must not change once it has been read. For + * this reason, the `FormulaTag`'s `children` property is a function, which + * allows you to keep the tag stable while varying the children (which *are* + * allowed to change, since that's the point of `FormulaTag`). + */ export interface Tagged { - [TAG]: I; + readonly [TAG]: I; } export interface ReactiveValue diff --git a/packages/universal/tags/index.ts b/packages/universal/tags/index.ts index 5f5f6117..c48bb594 100644 --- a/packages/universal/tags/index.ts +++ b/packages/universal/tags/index.ts @@ -1,4 +1,5 @@ export { CellTag, DelegateTag, FormulaTag, StaticTag, Tag } from "./src/tag.js"; +export { getTag } from "./src/tagged.js"; export { debug as debugTimestamp, getNow, diff --git a/packages/universal/tags/src/tagged.ts b/packages/universal/tags/src/tagged.ts new file mode 100644 index 00000000..55025f64 --- /dev/null +++ b/packages/universal/tags/src/tagged.ts @@ -0,0 +1,6 @@ +import type { Tag, Tagged } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; + +export function getTag(tagged: Tagged): T { + return tagged[TAG]; +} diff --git a/packages/universal/timeline/src/timeline/frame.ts b/packages/universal/timeline/src/timeline/frame.ts index 9ba76732..7a461be7 100644 --- a/packages/universal/timeline/src/timeline/frame.ts +++ b/packages/universal/timeline/src/timeline/frame.ts @@ -97,6 +97,7 @@ export class Frame #children: ReadonlySet; #finalized: Timestamp; readonly #description: Description; + readonly [TAG]: FormulaTag; constructor( value: T | UNINITIALIZED, @@ -114,10 +115,7 @@ export class Frame this.#children = children; this.#finalized = finalized; this.#description = description; - } - - get [TAG](): FormulaTag { - return FormulaTag.create(this.#description, () => [ + this[TAG] = FormulaTag.create(this.#description, () => [ this.#initialized, ...this.#children, ]); diff --git a/packages/universal/timeline/src/timeline/frames.ts b/packages/universal/timeline/src/timeline/frames.ts index a7b3b683..3a8dbce0 100644 --- a/packages/universal/timeline/src/timeline/frames.ts +++ b/packages/universal/timeline/src/timeline/frames.ts @@ -2,8 +2,8 @@ import type { DebugTimeline, Stack } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; import type { CellTag, Tagged } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; +import { getTag } from "@starbeam/tags"; -import { TaggedUtils } from "../utils/utils.js"; import { ActiveFrame, type Frame } from "./frame.js"; import type { Subscriptions } from "./subscriptions.js"; import type { Timeline } from "./timeline.js"; @@ -96,12 +96,10 @@ export class FrameStack { frame.add(reactive); return; } else { - const delegatesTo = TaggedUtils.subscriptionTargets(reactive).filter( - (r) => TaggedUtils.is(r, "cell") - ); + const delegatesTo = [...getTag(reactive).subscriptionTargets()]; for (const target of delegatesTo) { - if (TaggedUtils.is(target, "cell")) { + if (target.type === "cell") { this.#timeline.untrackedRead(target, caller); } } diff --git a/packages/universal/timeline/src/timeline/subscriptions.ts b/packages/universal/timeline/src/timeline/subscriptions.ts index e26f06c9..0967f3ae 100644 --- a/packages/universal/timeline/src/timeline/subscriptions.ts +++ b/packages/universal/timeline/src/timeline/subscriptions.ts @@ -1,4 +1,11 @@ -import type { CellTag, Diff, FormulaTag, Tagged } from "@starbeam/interfaces"; +import type { + CellTag, + Diff, + FormulaTag, + Tag, + Tagged, +} from "@starbeam/interfaces"; +import { getTag } from "@starbeam/tags"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { TaggedUtils } from "../utils/utils.js"; @@ -70,11 +77,11 @@ export class Subscriptions { * different dependencies. */ register(target: Tagged, ready: NotifyReady): Unsubscribe { - const subscriptionTargets = TaggedUtils.subscriptionTargets(target); + const subscriptionTargets = getTag(target).subscriptionTargets(); - const unsubscribes = subscriptionTargets.map((t) => { + const unsubscribes = [...subscriptionTargets].map((t) => { const entry = this.#formulaMap.register(t); - for (const dependency of TaggedUtils.dependencies(t)) { + for (const dependency of t.dependencies()) { this.#cellMap.register(dependency, entry); } @@ -117,18 +124,18 @@ class SubscriberMap { return new SubscriberMap(); } - readonly #mapping = new WeakMap(); + readonly #mapping = new WeakMap(); update( frame: Tagged ): Diff & { entry: ReactiveSubscription } { - const entry = this.#mapping.get(frame); + const entry = this.#mapping.get(getTag(frame)); if (entry) { return { ...entry.update(frame), entry }; } else { - const entry = ReactiveSubscription.create(frame); - this.#mapping.set(frame, entry); + const entry = ReactiveSubscription.create(getTag(frame)); + this.#mapping.set(getTag(frame), entry); return { add: new Set(TaggedUtils.dependencies(frame)), remove: new Set(), @@ -137,7 +144,7 @@ class SubscriberMap { } } - register(target: Tagged): ReactiveSubscription { + register(target: Tag): ReactiveSubscription { let entry = this.#mapping.get(target); if (!entry) { @@ -150,8 +157,8 @@ class SubscriberMap { } class ReactiveSubscription { - static create(target: Tagged): ReactiveSubscription { - const deps = new Set(TaggedUtils.dependencies(target)); + static create(target: Tag): ReactiveSubscription { + const deps = new Set(target.dependencies()); return new ReactiveSubscription(deps); } diff --git a/packages/universal/timeline/src/timeline/timeline.ts b/packages/universal/timeline/src/timeline/timeline.ts index 4e16c57b..5d03f1d1 100644 --- a/packages/universal/timeline/src/timeline/timeline.ts +++ b/packages/universal/timeline/src/timeline/timeline.ts @@ -51,7 +51,9 @@ export class Timeline { * Dynamic assertions that are used in development mode to detect reads that occur outside of a * tracking frame, but which are used to produce rendered outputs. */ - #readAssertions = new Set<(reactive: Tagged, caller: Stack) => void>(); + #readAssertions = new Set< + (reactive: interfaces.Tag, caller: Stack) => void + >(); readonly #subscriptions: Subscriptions; #lastOp: TimelineOp; @@ -62,7 +64,7 @@ export class Timeline { * produce rendered content. */ declare untrackedReadBarrier: ( - assertion: (reactive: Tagged, caller: Stack) => void + assertion: (reactive: interfaces.Tag, caller: Stack) => void ) => void; static create(): Timeline { @@ -76,7 +78,7 @@ export class Timeline { if (import.meta.env.DEV) { this.untrackedReadBarrier = ( - assertion: (reactive: Tagged, caller: Stack) => void + assertion: (reactive: interfaces.Tag, caller: Stack) => void ): void => { this.#readAssertions.add(assertion); }; @@ -178,7 +180,7 @@ export class Timeline { /// DEBUG MODE /// /** @internal */ - untrackedRead(cell: Tagged, caller: Stack): void { + untrackedRead(cell: CellTag, caller: Stack): void { for (const assertion of this.#readAssertions) { assertion(cell, caller); } diff --git a/packages/universal/timeline/src/utils/tagged.ts b/packages/universal/timeline/src/utils/tagged.ts index 75cf8407..927887b2 100644 --- a/packages/universal/timeline/src/utils/tagged.ts +++ b/packages/universal/timeline/src/utils/tagged.ts @@ -1,8 +1,8 @@ import type * as Debug from "@starbeam/debug"; import { debugTag, logTag } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { Matcher, Tag } from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; +import type { Matcher, SpecificTag, TagType } from "@starbeam/interfaces"; +import { getTag, type Tag } from "@starbeam/tags"; import { type Timestamp, zero } from "@starbeam/tags"; export type Tagged = @@ -10,65 +10,40 @@ export type Tagged = export const TaggedUtils = new (class { description(this: void, reactive: Tagged): Debug.Description { - return reactive[TAG].description; + return getTag(reactive).description; } id(this: void, reactive: Tagged): interfaces.ReactiveId { - return reactive[TAG].id; + return getTag(reactive).id; } - is( + is( this: void, reactive: Tagged, kind: T - ): reactive is { - [TAG]: Extract; - } { - return reactive[TAG].type === kind; + ): reactive is Tagged> { + return getTag(reactive).type === kind; } match(this: void, reactive: Tagged, matcher: Matcher): T { - return reactive[TAG].match(matcher) as T; - } - - /** - * This method returns a list of reactives that subscribers to the original reactive should - * actually subscribe to. - * - * Normally, this is just the reactive itself. However, if a ReactiveProtocol is a delegate, - * subscribers can subscribe directly to the delegate's targets. - * - * This is because a delegate's targets can't change, so it's safe to subscribe directly to the - * targets. - * - * This makes it possible to create abstractions around reactive values that don't have to worry - * about manually updating their subscribers when their values change. - */ - subscriptionTargets(this: void, reactive: Tagged): Tagged[] { - const tag = reactive[TAG]; - - if (tag.type === "delegate") { - return tag.targets.flatMap(TaggedUtils.subscriptionTargets); - } else { - return [reactive]; - } + return getTag(reactive).match(matcher) as T; } dependencies(this: void, reactive: Tagged): Iterable { - return reactive[TAG].dependencies(); + return getTag(reactive).dependencies(); } *dependenciesInList( this: void, children: readonly Tagged[] ): Iterable { - for (const child of children) { - yield* child[TAG].dependencies(); + for (const child of children.map(getTag)) { + yield* child.dependencies(); } } lastUpdated(this: void, reactive: Tagged): Timestamp { - return reactive[TAG].lastUpdated; + return getTag(reactive).lastUpdated; } lastUpdatedIn(this: void, reactives: Tagged[]): Timestamp { @@ -88,7 +63,7 @@ export const TaggedUtils = new (class { reactive: Tagged, options: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): void { - logTag(reactive[TAG], options); + logTag(getTag(reactive), options); } debug( @@ -99,7 +74,7 @@ export const TaggedUtils = new (class { source = false, }: { implementation?: boolean; source?: boolean } = {} ): string { - return debugTag(reactive[TAG], { + return debugTag(getTag(reactive), { implementation, source, }); diff --git a/packages/universal/universal/src/reactive-core/cell.ts b/packages/universal/universal/src/reactive-core/cell.ts index 5afd96a2..b7a0efde 100644 --- a/packages/universal/universal/src/reactive-core/cell.ts +++ b/packages/universal/universal/src/reactive-core/cell.ts @@ -31,19 +31,20 @@ export class ReactiveCell implements ReactiveValue { } #value: T; - readonly #tag: CellTag; readonly #equals: Equality; + readonly [TAG]: CellTag; declare [INSPECT]: () => object; private constructor(value: T, equals: Equality, tag: CellTag) { this.#value = value; this.#equals = equals; - this.#tag = tag; + + this[TAG] = tag; if (import.meta.env.DEV) { this[INSPECT] = (): object => { - const { description, lastUpdated } = this.#tag; + const { description, lastUpdated } = this[TAG]; const desc = ` (${description.describe()})`; @@ -53,6 +54,10 @@ export class ReactiveCell implements ReactiveValue { }); }; + Object.defineProperty(this, TAG, { + writable: false, + }); + Object.defineProperty(this, "toString", { enumerable: false, configurable: true, @@ -63,7 +68,7 @@ export class ReactiveCell implements ReactiveValue { } freeze(): void { - this.#tag.freeze(); + this[TAG].freeze(); } get current(): T { @@ -105,13 +110,9 @@ export class ReactiveCell implements ReactiveValue { } this.#value = value; - this.#tag.update({ timeline: TIMELINE, stack: caller }); + this[TAG].update({ timeline: TIMELINE, stack: caller }); return true; } - - get [TAG](): CellTag { - return this.#tag; - } } const INITIAL_INTERNAL_FRAMES = 0; diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts index 42344b8b..3f2d780c 100644 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ b/packages/universal/universal/src/reactive-core/marker.ts @@ -9,18 +9,20 @@ export class ReactiveMarker implements Tagged { return new ReactiveMarker(tag); } - readonly #tag: CellTag; + readonly [TAG]: CellTag; private constructor(tag: CellTag) { - this.#tag = tag; - } + this[TAG] = tag; - get [TAG](): CellTag { - return this.#tag; + if (import.meta.env.DEV) { + Object.defineProperty(this, TAG, { + writable: false, + }); + } } freeze(): void { - this.#tag.freeze(); + this[TAG].freeze(); } consume(caller = callerStack()): void { @@ -28,7 +30,7 @@ export class ReactiveMarker implements Tagged { } update(caller: Stack): void { - this.#tag.update({ timeline: TIMELINE, stack: caller }); + this[TAG].update({ timeline: TIMELINE, stack: caller }); } } From ff95ee1957579c6f4f4c80e409c55bb04014a929 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 23 Mar 2023 18:34:40 -0700 Subject: [PATCH 05/46] WIP --- packages/react/react/src/debug/warnings.ts | 6 +- packages/universal/debug/src/timeline.ts | 19 ++--- packages/universal/js/package.json | 1 + packages/universal/js/src/collection.ts | 4 +- packages/universal/modifier/package.json | 1 + packages/universal/modifier/src/modifier.ts | 8 +- packages/universal/tags/index.ts | 8 +- packages/universal/tags/src/tagged.ts | 44 +++++++++- packages/universal/timeline/index.ts | 4 +- .../universal/timeline/src/timeline/frame.ts | 4 +- .../timeline/src/timeline/subscriptions.ts | 5 +- .../timeline/src/timeline/timeline.ts | 5 +- .../universal/timeline/src/utils/tagged.ts | 82 ------------------- .../universal/timeline/src/utils/utils.ts | 1 - .../universal/timeline/tests/protocol.spec.ts | 50 ++++++----- .../universal/src/reactive-core/delegate.ts | 8 +- .../src/reactive-core/formula/formula.ts | 7 +- .../reactive-core/formula/polled-formula.ts | 10 +-- .../universal/universal/tests/factory.spec.ts | 7 +- .../universal/universal/tests/setup.spec.ts | 23 +++--- .../universal/tests/variants.spec.ts | 8 +- pnpm-lock.yaml | 4 + 22 files changed, 139 insertions(+), 170 deletions(-) delete mode 100644 packages/universal/timeline/src/utils/tagged.ts diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index 40f02a15..ff3fb271 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,16 +1,16 @@ import { Message } from "@starbeam/debug"; -import { TaggedUtils, TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "@starbeam/timeline"; import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; if (import.meta.env.DEV) { - TIMELINE.untrackedReadBarrier((reactive, stack) => { + TIMELINE.untrackedReadBarrier((tag, stack) => { if (isRendering()) { if (!WARNED) { WARNED = true; - const description = TaggedUtils.description(reactive).userFacing; + const description = tag.description.userFacing; const caller = stack.caller; const pad = Math.max( diff --git a/packages/universal/debug/src/timeline.ts b/packages/universal/debug/src/timeline.ts index e8a29bbc..0afcc94a 100644 --- a/packages/universal/debug/src/timeline.ts +++ b/packages/universal/debug/src/timeline.ts @@ -11,8 +11,8 @@ import type { import { TAG } from "@starbeam/shared"; import { exhaustive } from "@starbeam/verify"; -interface SubscriptionTargetStatics { - dependencies: (reactive: Tagged) => Iterable; +interface Runtime { + getTag: (reactive: Tagged) => Tag; } function reactiveInternals(reactive: Tagged): Tag { @@ -128,11 +128,11 @@ export type DebugFilter = function filterToPredicate( filter: DebugFilter, - reactive: SubscriptionTargetStatics + reactive: Runtime ): ((operation: DebugOperation) => boolean) | undefined { switch (filter.type) { case "by-reactive": { - const dependencies = reactive.dependencies(filter.reactive); + const dependencies = reactive.getTag(filter.reactive).dependencies(); // const dependencies = reactiveDependencies(filter.reactive).children() // .dependencies; @@ -161,7 +161,7 @@ const INITIAL_OFFSET = 0; export class DebugTimeline { #timestamp: { now: () => Timestamp }; - #statics: SubscriptionTargetStatics; + #statics: Runtime; #trimOffset = INITIAL_OFFSET; #operationList: DebugOperation[] = []; #currentMutation: MutationLog | null = null; @@ -198,7 +198,7 @@ export class DebugTimeline { static create( timestamp: { now: () => Timestamp }, - statics: SubscriptionTargetStatics + statics: Runtime ): DebugTimeline { return new DebugTimeline(timestamp, statics); } @@ -229,15 +229,12 @@ export class DebugTimeline { static create( timestamp: { now: () => Timestamp }, - statics: SubscriptionTargetStatics + statics: Runtime ): DebugTimeline { return new DebugTimeline(timestamp, statics); } - private constructor( - timestamp: { now: () => Timestamp }, - statics: SubscriptionTargetStatics - ) { + private constructor(timestamp: { now: () => Timestamp }, statics: Runtime) { this.#timestamp = timestamp; this.#statics = statics; } diff --git a/packages/universal/js/package.json b/packages/universal/js/package.json index dbac605c..5d16828b 100644 --- a/packages/universal/js/package.json +++ b/packages/universal/js/package.json @@ -29,6 +29,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/timeline": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" diff --git a/packages/universal/js/src/collection.ts b/packages/universal/js/src/collection.ts index 31a1fcb0..f9df59aa 100644 --- a/packages/universal/js/src/collection.ts +++ b/packages/universal/js/src/collection.ts @@ -1,5 +1,5 @@ import type { Description, Stack } from "@starbeam/debug"; -import { TaggedUtils } from "@starbeam/timeline"; +import { taggedDescription } from "@starbeam/tags"; import { Cell, Marker } from "@starbeam/universal"; import { expected, isPresent, verified } from "@starbeam/verify"; @@ -203,7 +203,7 @@ export class Collection { } let item: Item; - const iteration = TaggedUtils.description(this.#iteration); + const iteration = taggedDescription(this.#iteration); if (disposition === "miss") { item = Item.uninitialized(iteration, member, caller); diff --git a/packages/universal/modifier/package.json b/packages/universal/modifier/package.json index d06c80cb..7e2d0d75 100644 --- a/packages/universal/modifier/package.json +++ b/packages/universal/modifier/package.json @@ -27,6 +27,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/universal/modifier/src/modifier.ts b/packages/universal/modifier/src/modifier.ts index 83b870e3..c31fc522 100644 --- a/packages/universal/modifier/src/modifier.ts +++ b/packages/universal/modifier/src/modifier.ts @@ -2,7 +2,8 @@ import type { anydom } from "@domtree/flavors"; import { type Description, REUSE_ID } from "@starbeam/debug"; import type { Tagged } from "@starbeam/interfaces"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; -import { Cell, DelegateInternals } from "@starbeam/universal"; +import { DelegateTag } from "@starbeam/tags"; +import { Cell } from "@starbeam/universal"; import { expected, isPresent, verified, verify } from "@starbeam/verify"; export type ElementType = abstract new < @@ -13,8 +14,7 @@ export type ElementType = abstract new < // export type Ref = Initializable; -export interface ElementPlaceholder - extends Tagged { +export interface ElementPlaceholder extends Tagged { readonly initialize: (value: E) => void; readonly current: E | null; } @@ -35,7 +35,7 @@ export function ElementPlaceholder( REFS.set(ref, elementCell); return { - [TAG]: DelegateInternals([elementCell]), + [TAG]: DelegateTag.create(description, [elementCell]), initialize(value: anydom.Element): void { const element = verified(REFS.get(ref), isPresent); diff --git a/packages/universal/tags/index.ts b/packages/universal/tags/index.ts index c48bb594..42d8ad3d 100644 --- a/packages/universal/tags/index.ts +++ b/packages/universal/tags/index.ts @@ -1,5 +1,11 @@ export { CellTag, DelegateTag, FormulaTag, StaticTag, Tag } from "./src/tag.js"; -export { getTag } from "./src/tagged.js"; +export { + dependenciesInTaggedList, + describeTagged, + getTag, + lastUpdatedInTaggedList, + taggedDescription, +} from "./src/tagged.js"; export { debug as debugTimestamp, getNow, diff --git a/packages/universal/tags/src/tagged.ts b/packages/universal/tags/src/tagged.ts index 55025f64..bc087a11 100644 --- a/packages/universal/tags/src/tagged.ts +++ b/packages/universal/tags/src/tagged.ts @@ -1,6 +1,48 @@ -import type { Tag, Tagged } from "@starbeam/interfaces"; +import type { + CellTag, + Description, + DescriptionDescribeOptions, + Tag, + Tagged, + Timestamp, +} from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; +import { zero } from "./timestamp.js"; + export function getTag(tagged: Tagged): T { return tagged[TAG]; } + +export function describeTagged( + tagged: Tagged, + options?: DescriptionDescribeOptions +): string { + return getTag(tagged).description.describe(options); +} + +export function taggedDescription(tagged: Tagged): Description { + return getTag(tagged).description; +} + +export function* dependenciesInTaggedList( + taggedList: readonly Tagged[] +): Iterable { + for (const child of taggedList.map(getTag)) { + yield* child.dependencies(); + } +} + +export function lastUpdatedInTaggedList( + taggedList: readonly Tagged[] +): Timestamp { + let lastUpdatedTimestamp = zero(); + + for (const child of dependenciesInTaggedList(taggedList)) { + if (child.lastUpdated.gt(lastUpdatedTimestamp)) { + lastUpdatedTimestamp = child.lastUpdated; + } + } + + return lastUpdatedTimestamp; +} diff --git a/packages/universal/timeline/index.ts b/packages/universal/timeline/index.ts index 83432a17..b8826c07 100644 --- a/packages/universal/timeline/index.ts +++ b/packages/universal/timeline/index.ts @@ -21,11 +21,11 @@ export { Subscriptions, } from "./src/timeline/subscriptions.js"; export { diff } from "./src/timeline/utils.js"; -export { Reactive, TaggedUtils } from "./src/utils/utils.js"; +export { Reactive } from "./src/utils/utils.js"; export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; import type * as interfaces from "@starbeam/interfaces"; export type { interfaces }; -export { Timestamp } from "@starbeam/tags"; +export { getTag, Timestamp } from "@starbeam/tags"; diff --git a/packages/universal/timeline/src/timeline/frame.ts b/packages/universal/timeline/src/timeline/frame.ts index 7a461be7..259ab0a1 100644 --- a/packages/universal/timeline/src/timeline/frame.ts +++ b/packages/universal/timeline/src/timeline/frame.ts @@ -7,9 +7,9 @@ import type { import type * as interfaces from "@starbeam/interfaces"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; import { CellTag, FormulaTag, getNow } from "@starbeam/tags"; +import { lastUpdatedInTaggedList } from "@starbeam/tags/src/tagged.js"; import { isNotEqual, verified } from "@starbeam/verify"; -import { TaggedUtils } from "../utils/utils.js"; import type { FrameStack } from "./frames.js"; import { getID } from "./id.js"; import type { Timeline } from "./timeline.js"; @@ -154,7 +154,7 @@ export class Frame validate(): FrameValidation> { if ( this.#value === UNINITIALIZED || - TaggedUtils.lastUpdatedIn([...this.#children]).gt(this.#finalized) + lastUpdatedInTaggedList([...this.#children]).gt(this.#finalized) ) { return { status: "invalid" }; } else { diff --git a/packages/universal/timeline/src/timeline/subscriptions.ts b/packages/universal/timeline/src/timeline/subscriptions.ts index 0967f3ae..0a5d1ba6 100644 --- a/packages/universal/timeline/src/timeline/subscriptions.ts +++ b/packages/universal/timeline/src/timeline/subscriptions.ts @@ -8,7 +8,6 @@ import type { import { getTag } from "@starbeam/tags"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; -import { TaggedUtils } from "../utils/utils.js"; import { diff } from "./utils.js"; export type NotifyReady = (internals: CellTag) => void; @@ -137,7 +136,7 @@ class SubscriberMap { const entry = ReactiveSubscription.create(getTag(frame)); this.#mapping.set(getTag(frame), entry); return { - add: new Set(TaggedUtils.dependencies(frame)), + add: new Set(getTag(frame).dependencies()), remove: new Set(), entry, }; @@ -182,7 +181,7 @@ class ReactiveSubscription { update(frame: Tagged): Diff { const prev = this.#deps; - const next = new Set(TaggedUtils.dependencies(frame)); + const next = new Set(getTag(frame).dependencies()); this.#deps = next; return diff(prev, next); diff --git a/packages/universal/timeline/src/timeline/timeline.ts b/packages/universal/timeline/src/timeline/timeline.ts index 5d03f1d1..af8eb254 100644 --- a/packages/universal/timeline/src/timeline/timeline.ts +++ b/packages/universal/timeline/src/timeline/timeline.ts @@ -2,10 +2,9 @@ import type { Stack } from "@starbeam/debug"; import { DebugTimeline } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; import type { CellTag, Tagged } from "@starbeam/interfaces"; -import { getNow, NOW } from "@starbeam/tags"; +import { getNow, getTag, NOW } from "@starbeam/tags"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; -import { TaggedUtils } from "../utils/utils.js"; import { FrameStack } from "./frames.js"; import { type NotifyReady, Subscriptions } from "./subscriptions.js"; @@ -87,7 +86,7 @@ export class Timeline { get #debug(): DebugTimeline { if (!this.#debugTimeline) { - this.#debugTimeline = DebugTimeline.create({ now: getNow }, TaggedUtils); + this.#debugTimeline = DebugTimeline.create({ now: getNow }, { getTag }); } return this.#debugTimeline; diff --git a/packages/universal/timeline/src/utils/tagged.ts b/packages/universal/timeline/src/utils/tagged.ts deleted file mode 100644 index 927887b2..00000000 --- a/packages/universal/timeline/src/utils/tagged.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type * as Debug from "@starbeam/debug"; -import { debugTag, logTag } from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; -import type { Matcher, SpecificTag, TagType } from "@starbeam/interfaces"; -import { getTag, type Tag } from "@starbeam/tags"; -import { type Timestamp, zero } from "@starbeam/tags"; - -export type Tagged = - interfaces.Tagged; - -export const TaggedUtils = new (class { - description(this: void, reactive: Tagged): Debug.Description { - return getTag(reactive).description; - } - - id(this: void, reactive: Tagged): interfaces.ReactiveId { - return getTag(reactive).id; - } - - is( - this: void, - reactive: Tagged, - kind: T - ): reactive is Tagged> { - return getTag(reactive).type === kind; - } - - match(this: void, reactive: Tagged, matcher: Matcher): T { - return getTag(reactive).match(matcher) as T; - } - - dependencies(this: void, reactive: Tagged): Iterable { - return getTag(reactive).dependencies(); - } - - *dependenciesInList( - this: void, - children: readonly Tagged[] - ): Iterable { - for (const child of children.map(getTag)) { - yield* child.dependencies(); - } - } - - lastUpdated(this: void, reactive: Tagged): Timestamp { - return getTag(reactive).lastUpdated; - } - - lastUpdatedIn(this: void, reactives: Tagged[]): Timestamp { - let lastUpdatedTimestamp = zero(); - - for (const child of TaggedUtils.dependenciesInList(reactives)) { - if (child.lastUpdated.gt(lastUpdatedTimestamp)) { - lastUpdatedTimestamp = child.lastUpdated; - } - } - - return lastUpdatedTimestamp; - } - - log( - this: void, - reactive: Tagged, - options: { implementation?: boolean; source?: boolean; id?: boolean } = {} - ): void { - logTag(getTag(reactive), options); - } - - debug( - this: void, - reactive: Tagged, - { - implementation = false, - source = false, - }: { implementation?: boolean; source?: boolean } = {} - ): string { - return debugTag(getTag(reactive), { - implementation, - source, - }); - } -})(); diff --git a/packages/universal/timeline/src/utils/utils.ts b/packages/universal/timeline/src/utils/utils.ts index 382e100f..97069c8d 100644 --- a/packages/universal/timeline/src/utils/utils.ts +++ b/packages/universal/timeline/src/utils/utils.ts @@ -1,2 +1 @@ export { Reactive } from "./reactive.js"; -export { TaggedUtils } from "./tagged.js"; diff --git a/packages/universal/timeline/tests/protocol.spec.ts b/packages/universal/timeline/tests/protocol.spec.ts index 86e6ce64..8a16be51 100644 --- a/packages/universal/timeline/tests/protocol.spec.ts +++ b/packages/universal/timeline/tests/protocol.spec.ts @@ -1,7 +1,14 @@ import { callerStack, Desc } from "@starbeam/debug"; import type { Tagged } from "@starbeam/interfaces"; -import { CellTag, FormulaTag, zero } from "@starbeam/tags"; -import { TAG, TaggedUtils, TIMELINE } from "@starbeam/timeline"; +import { + CellTag, + dependenciesInTaggedList, + FormulaTag, + getTag, + lastUpdatedInTaggedList, + zero, +} from "@starbeam/tags"; +import { TAG, TIMELINE } from "@starbeam/timeline"; import { beforeAll, describe, expect, it } from "vitest"; import { Cell, FreezableCell, Static } from "./support/mini-reactives.js"; @@ -16,15 +23,15 @@ describe("Tagged", () => { it("has the zero timestamp for lastUpdated", () => { const tom = Static("Tom Dale"); - expect(String(TaggedUtils.lastUpdated(tom))).toBe(String(zero())); - expect(String(TaggedUtils.lastUpdatedIn([tom]))).toBe(String(zero())); + expect(String(getTag(tom).lastUpdated)).toBe(String(zero())); + expect(String(lastUpdatedInTaggedList([tom]))).toBe(String(zero())); }); it("has no dependencies", () => { const tom = Static("Tom Dale"); - expect([...TaggedUtils.dependencies(tom)]).toEqual([]); - expect([...TaggedUtils.dependenciesInList([tom])]).toEqual([]); + expect([...getTag(tom).dependencies()]).toEqual([]); + expect([...dependenciesInTaggedList([tom])]).toEqual([]); }); }); @@ -32,16 +39,15 @@ describe("Tagged", () => { it("has the current timestamp for lastUpdated", () => { const original = TIMELINE.now; const tom = Cell("Tom"); - expect(String(TaggedUtils.lastUpdated(tom))).toBe(String(TIMELINE.now)); + expect(String(getTag(tom).lastUpdated)).toBe(String(TIMELINE.now)); const nullvox = Cell("nullvox"); const nullvoxTimestamp = TIMELINE.now; + expect(String(getTag(nullvox).lastUpdated), "lastUpdated(nullvox)").toBe( + String(nullvoxTimestamp) + ); expect( - String(TaggedUtils.lastUpdated(nullvox)), - "lastUpdated(nullvox)" - ).toBe(String(nullvoxTimestamp)); - expect( - String(TaggedUtils.lastUpdatedIn([tom, nullvox])), + String(lastUpdatedInTaggedList([tom, nullvox])), "lastUpdatedIn([tom,nullvox])" ).toBe(String(TIMELINE.now)); @@ -53,13 +59,13 @@ describe("Tagged", () => { tom.current = "Tom Dale"; console.log("wrote", TIMELINE.now); expect(String(TIMELINE.now), "TIMELINE.now").not.toBe(String(original)); - expect(String(TaggedUtils.lastUpdated(tom)), "lastUpdated(tom)").toBe( + expect(String(getTag(tom).lastUpdated), "lastUpdated(tom)").toBe( String(TIMELINE.now) ); - expect(String(TaggedUtils.lastUpdated(nullvox))).toBe( + expect(String(getTag(nullvox).lastUpdated)).toBe( String(nullvoxTimestamp) ); - expect(String(TaggedUtils.lastUpdatedIn([tom, nullvox]))).toBe( + expect(String(lastUpdatedInTaggedList([tom, nullvox]))).toBe( String(TIMELINE.now) ); }); @@ -68,8 +74,8 @@ describe("Tagged", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - expect([...TaggedUtils.dependencies(tom)]).toEqual([tom[TAG]]); - expect([...TaggedUtils.dependenciesInList([tom, nullvox])]).toEqual([ + expect([...getTag(tom).dependencies()]).toEqual([tom[TAG]]); + expect([...dependenciesInTaggedList([tom, nullvox])]).toEqual([ tom[TAG], nullvox[TAG], ]); @@ -82,8 +88,8 @@ describe("Tagged", () => { nullvox.current = "@nullvoxpopuli"; - expect([...TaggedUtils.dependencies(tom)]).toEqual([]); - expect([...TaggedUtils.dependenciesInList([tom, nullvox])]).toEqual([ + expect([...getTag(tom).dependencies()]).toEqual([]); + expect([...dependenciesInTaggedList([tom, nullvox])]).toEqual([ nullvox[TAG], ]); }); @@ -100,16 +106,16 @@ describe("Tagged", () => { [TAG]: formula, }; - expect(String(TaggedUtils.lastUpdated(Both))).toBe(String(TIMELINE.now)); + expect(String(getTag(Both).lastUpdated)).toBe(String(TIMELINE.now)); - expect([...TaggedUtils.dependencies(Both)]).toEqual([ + expect([...getTag(Both).dependencies()]).toEqual([ tom[TAG], nullvox[TAG], ]); tom.current = "Tom Dale"; - expect(String(TaggedUtils.lastUpdated(Both))).toBe(String(TIMELINE.now)); + expect(String(getTag(Both).lastUpdated)).toBe(String(TIMELINE.now)); }); }); }); diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/universal/src/reactive-core/delegate.ts index d732962c..f3feff45 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/universal/src/reactive-core/delegate.ts @@ -1,7 +1,7 @@ import { callerStack, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { DelegateTag } from "@starbeam/tags"; -import { TAG, TaggedUtils } from "@starbeam/timeline"; +import { DelegateTag, taggedDescription } from "@starbeam/tags"; +import { TAG } from "@starbeam/timeline"; export function Wrap( reactive: U, @@ -37,9 +37,9 @@ function delegateDesc( if (Array.isArray(to)) { return desc as Description; } else if (typeof desc === "string") { - return TaggedUtils.description(to).detail(desc); + return taggedDescription(to).detail(desc); } else if (desc === undefined) { - return TaggedUtils.description(to).detail("{delegate}"); + return taggedDescription(to).detail("{delegate}"); } else { return desc; } diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts index 7e28a467..07f6b796 100644 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/formula.ts @@ -5,8 +5,7 @@ import { } from "@starbeam/debug"; import type { Reactive, Stack } from "@starbeam/interfaces"; import type { UNINITIALIZED } from "@starbeam/shared"; -import { DelegateTag } from "@starbeam/tags"; -import { TaggedUtils } from "@starbeam/timeline"; +import { DelegateTag, getTag } from "@starbeam/tags"; import { diff, Frame, TAG, TIMELINE } from "@starbeam/timeline"; export interface FormulaValidation { @@ -31,13 +30,13 @@ export function FormulaValidation( const update = (caller: Stack): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(TaggedUtils.dependencies(frame)); + const oldDeps = new Set(getTag(frame).dependencies()); frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(TaggedUtils.dependencies(frame)); + const newDeps = new Set(getTag(frame).dependencies()); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts index 2d7376fa..fb2e2ba7 100644 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts @@ -6,8 +6,8 @@ import { } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; import type { UNINITIALIZED } from "@starbeam/shared"; -import { DelegateTag } from "@starbeam/tags"; -import { diff, Frame, TAG, TaggedUtils, TIMELINE } from "@starbeam/timeline"; +import { DelegateTag, getTag } from "@starbeam/tags"; +import { diff, Frame, TAG, TIMELINE } from "@starbeam/timeline"; import type { Formula } from "./formula.js"; @@ -44,12 +44,12 @@ export function PolledFormulaValidation( const update = (caller: Stack = callerStack()): void => { if (import.meta.env.DEV) { - const oldDeps = new Set(TaggedUtils.dependencies(frame)); + const oldDeps = new Set(getTag(frame).dependencies()); frame.evaluate(callback, TIMELINE.frame); TIMELINE.update(frame); - const newDeps = new Set(TaggedUtils.dependencies(frame)); + const newDeps = new Set(getTag(frame).dependencies()); TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); } else { @@ -97,7 +97,7 @@ export function PolledFormula( enumerable: false, configurable: true, writable: true, - value: DelegateTag.create(desc, [formula.frame]), + value: DelegateTag.create(desc, [formula.frame]), }); return fn as Formula; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index b6d8da00..33fe5591 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,5 +1,6 @@ import { entryPointFn } from "@starbeam/debug"; -import { Frame, TaggedUtils } from "@starbeam/timeline"; +import { describeTagged } from "@starbeam/tags"; +import { Frame } from "@starbeam/timeline"; import { Cell, FormulaValidation, Reactive, Static } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; @@ -36,9 +37,7 @@ describe("reactive Factory", () => { const counter = Counter.create(); if (!import.meta.env.PROD) { - expect(TaggedUtils.description(counter).describe()).toBe( - "Counter 0" - ); + expect(describeTagged(counter)).toBe("Counter 0"); } expect(counter.current).toBe(0); diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts index da5551c8..62fc5c31 100644 --- a/packages/universal/universal/tests/setup.spec.ts +++ b/packages/universal/universal/tests/setup.spec.ts @@ -1,4 +1,5 @@ -import { TaggedUtils, TIMELINE } from "@starbeam/timeline"; +import { getTag } from "@starbeam/tags"; +import { TIMELINE } from "@starbeam/timeline"; import { Cell, Setup } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -129,11 +130,11 @@ describe("Setup", () => { cleanupCounter: 0, }); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); setup(); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -143,11 +144,11 @@ describe("Setup", () => { // cellB is not used in the initial setup, so it doesn't invalidate the setup cellB.set(20); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); setup(); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 0, @@ -157,8 +158,8 @@ describe("Setup", () => { cellA.set(1); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = TaggedUtils.lastUpdated(setup); + expect(getTag(setup).lastUpdated).toSatisfy(gt(ts)); + ts = getTag(setup).lastUpdated; expect(variable).toEqual({ cell: 0, @@ -168,7 +169,7 @@ describe("Setup", () => { setup(); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 20, @@ -178,8 +179,8 @@ describe("Setup", () => { cellA.set(2); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(gt(ts)); - ts = TaggedUtils.lastUpdated(setup); + expect(getTag(setup).lastUpdated).toSatisfy(gt(ts)); + ts = getTag(setup).lastUpdated; expect(variable).toEqual({ cell: 20, @@ -189,7 +190,7 @@ describe("Setup", () => { setup(); - expect(TaggedUtils.lastUpdated(setup)).toSatisfy(eq(ts)); + expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); expect(variable).toEqual({ cell: 2, diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 2d2dd081..5e10c466 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,4 +1,5 @@ -import { type Tagged, TaggedUtils } from "@starbeam/timeline"; +import { describeTagged } from "@starbeam/tags"; +import { type Tagged } from "@starbeam/timeline"; import { Formula, TIMELINE, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -202,10 +203,7 @@ function Stability(reactive: Tagged): { TIMELINE.on.change(reactive, (internals) => { if (debug) { - console.group( - TaggedUtils.description(reactive).describe(), - "invalidated by" - ); + console.group(describeTagged(reactive), "invalidated by"); console.log(internals.description.describe()); console.groupEnd(); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2d2c13f..7ba04a15 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -721,6 +721,7 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ '@starbeam/shared': workspace:^ + '@starbeam/tags': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ @@ -728,6 +729,7 @@ importers: '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces '@starbeam/shared': link:../shared + '@starbeam/tags': link:../tags '@starbeam/timeline': link:../timeline '@starbeam/universal': link:../universal '@starbeam/verify': link:../verify @@ -749,12 +751,14 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ '@starbeam/shared': workspace:^ + '@starbeam/tags': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ dependencies: '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces '@starbeam/shared': link:../shared + '@starbeam/tags': link:../tags '@starbeam/universal': link:../universal '@starbeam/verify': link:../verify devDependencies: From 0f07706d8cbb6866df2e6ef60fea4791d39edfac Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 23 Mar 2023 22:02:15 -0700 Subject: [PATCH 06/46] Consolidate and simplify the core types Also consolidate and simplify the functions for interacting with them --- packages/preact/preact/src/options.ts | 4 +- packages/react/react/src/use-setup.ts | 6 +- packages/react/react/src/utils.ts | 4 +- .../react/react/tests/use-resource.spec.ts | 9 +-- .../universal/interfaces/src/protocol.d.ts | 2 +- packages/universal/timeline/index.ts | 13 ++-- .../universal/timeline/src/utils/reactive.ts | 63 +++++++++++++------ .../universal/timeline/src/utils/utils.ts | 1 - packages/universal/universal/index.ts | 1 - .../universal/src/reactive-core/into.ts | 9 +-- .../universal/src/reactive-core/reactive.ts | 24 ++----- .../src/reactive-core/resource/resource.ts | 5 +- .../src/reactive-core/resource/state.ts | 12 ++-- .../universal/src/reactive-core/service.ts | 2 +- .../universal/src/reactive-core/static.ts | 16 ----- .../universal/universal/tests/custom.spec.ts | 13 ++-- .../universal/universal/tests/factory.spec.ts | 4 +- packages/x/devtool/package.json | 3 +- .../x/devtool/src/single/single-reactive.tsx | 29 ++++----- pnpm-lock.yaml | 2 + 20 files changed, 114 insertions(+), 108 deletions(-) delete mode 100644 packages/universal/timeline/src/utils/utils.ts delete mode 100644 packages/universal/universal/src/reactive-core/static.ts diff --git a/packages/preact/preact/src/options.ts b/packages/preact/preact/src/options.ts index d9fbfcb4..01294622 100644 --- a/packages/preact/preact/src/options.ts +++ b/packages/preact/preact/src/options.ts @@ -4,7 +4,7 @@ import type { InternalElement, } from "@starbeam/preact-utils"; import { Plugin } from "@starbeam/preact-utils"; -import { CONTEXT, LIFETIME, Reactive } from "@starbeam/timeline"; +import { CONTEXT, isReactive, LIFETIME } from "@starbeam/timeline"; import type { ComponentType } from "preact"; import { ComponentFrame } from "./frame.js"; @@ -22,7 +22,7 @@ export const setup = Plugin((on) => { on.vnode((vnode) => { vnode.processChildren((child) => { - if (Reactive.is(child)) { + if (isReactive(child)) { return String(child.read()); } else { return child; diff --git a/packages/react/react/src/use-setup.ts b/packages/react/react/src/use-setup.ts index 97fe1c27..46221ffb 100644 --- a/packages/react/react/src/use-setup.ts +++ b/packages/react/react/src/use-setup.ts @@ -1,6 +1,8 @@ import { callerStack, Desc } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; -import { PolledFormula, Reactive } from "@starbeam/universal"; +import { isReactive } from "@starbeam/timeline"; +import type { Reactive } from "@starbeam/universal"; +import { PolledFormula } from "@starbeam/universal"; import { setupFunction, unsafeTrackedElsewhere, @@ -73,7 +75,7 @@ export function useSetup< let currentProps: unknown = undefined; - if (Reactive.is(instance)) { + if (isReactive(instance)) { ReactiveElement.subscribe(element, instance); return { element, instance: { type: "reactive", value: instance } }; } else if (typeof instance === "function") { diff --git a/packages/react/react/src/utils.ts b/packages/react/react/src/utils.ts index 35ab73bb..3abeca7c 100644 --- a/packages/react/react/src/utils.ts +++ b/packages/react/react/src/utils.ts @@ -1,6 +1,6 @@ -import { type Description, Desc } from "@starbeam/debug"; +import { Desc, type Description } from "@starbeam/debug"; +import type { Reactive } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import type { Reactive } from "@starbeam/timeline"; import { Cell } from "@starbeam/universal"; import { useRef } from "react"; diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index 07cb472b..151d55b4 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -3,12 +3,13 @@ import { entryPoint } from "@starbeam/debug"; import reactive from "@starbeam/js"; import { use, useProp, useReactive, useSetup } from "@starbeam/react"; -import { Reactive } from "@starbeam/timeline"; +import { intoReactive } from "@starbeam/timeline"; import { - type ResourceBlueprint, Cell, Formula, + type IntoReactive, Resource, + type ResourceBlueprint, } from "@starbeam/universal"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; import { beforeEach, describe, expect } from "vitest"; @@ -420,9 +421,9 @@ function send(message: string): void { } function ChannelResource( - name: Reactive | string + name: IntoReactive ): ResourceBlueprint { - const reactive = Reactive.from(name); + const reactive = intoReactive(name); return Resource((r) => { const lastMessage = Cell(undefined, "last message"); diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index ffa5b146..53e0a81a 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -11,7 +11,7 @@ export interface AbstractTag { readonly description: Description; } -export type List = Iterable | readonly T[]; +export type List = Iterable; export class TagMethods { readonly id: ReactiveId; diff --git a/packages/universal/timeline/index.ts b/packages/universal/timeline/index.ts index b8826c07..4ec06903 100644 --- a/packages/universal/timeline/index.ts +++ b/packages/universal/timeline/index.ts @@ -21,11 +21,14 @@ export { Subscriptions, } from "./src/timeline/subscriptions.js"; export { diff } from "./src/timeline/utils.js"; -export { Reactive } from "./src/utils/utils.js"; +export { + intoReactive, + isReactive, + read, + Static, +} from "./src/utils/reactive.js"; export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; - -import type * as interfaces from "@starbeam/interfaces"; -export type { interfaces }; - export { getTag, Timestamp } from "@starbeam/tags"; +export type { interfaces }; +import type * as interfaces from "@starbeam/interfaces"; diff --git a/packages/universal/timeline/src/utils/reactive.ts b/packages/universal/timeline/src/utils/reactive.ts index bb8e4fc1..fa1b5807 100644 --- a/packages/universal/timeline/src/utils/reactive.ts +++ b/packages/universal/timeline/src/utils/reactive.ts @@ -1,5 +1,5 @@ import type * as Debug from "@starbeam/debug"; -import { Desc } from "@starbeam/debug"; +import { callerStack, Desc } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { StaticTag } from "@starbeam/tags"; @@ -17,33 +17,55 @@ function is( ); } -export const Reactive = { - is(this: void, value: unknown): value is interfaces.Reactive { - return is(value) && hasRead(value); - }, +export function isReactive( + this: void, + value: unknown +): value is Reactive { + return is(value) && hasRead(value); +} - from( - this: void, - value: T | Reactive, - description?: string | Debug.Description - ): Reactive { - if (Reactive.is(value)) { - return value; - } else { - return new Static(value, Desc("static", description)); - } - }, -}; +export function read( + this: void, + value: T | Reactive, + caller = callerStack() +): T { + if (is(value) && hasRead(value)) { + return value.read(caller); + } else { + return value; + } +} + +export function intoReactive( + this: void, + value: T | Reactive, + description?: string | Debug.Description +): Reactive { + if (isReactive(value)) { + return value; + } else { + return Static(value, Desc("static", description)); + } +} function hasRead(value: object): value is { read: () => T } { return "read" in value && typeof value.read === "function"; } -class Static implements interfaces.ReactiveValue { +export class StaticImpl + implements interfaces.ReactiveValue +{ + static create = ( + value: T, + description?: string | Debug.Description + ): StaticImpl => { + return new StaticImpl(value, Desc("static", description)); + }; + readonly #value: T; readonly [TAG]: interfaces.StaticTag; - constructor(value: T, description: Debug.Description) { + private constructor(value: T, description: Debug.Description) { this.#value = value; this[TAG] = StaticTag.create(description); } @@ -56,3 +78,6 @@ class Static implements interfaces.ReactiveValue { return this.#value; } } + +export const Static = StaticImpl.create; +export type Static = StaticImpl; diff --git a/packages/universal/timeline/src/utils/utils.ts b/packages/universal/timeline/src/utils/utils.ts deleted file mode 100644 index 97069c8d..00000000 --- a/packages/universal/timeline/src/utils/utils.ts +++ /dev/null @@ -1 +0,0 @@ -export { Reactive } from "./reactive.js"; diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index b5716227..a9aade7a 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -48,7 +48,6 @@ export { service, type ServiceBlueprint, } from "./src/reactive-core/service.js"; -export { Static } from "./src/reactive-core/static.js"; export { type Variant, type VariantEntry, diff --git a/packages/universal/universal/src/reactive-core/into.ts b/packages/universal/universal/src/reactive-core/into.ts index f82faee0..5b55e63d 100644 --- a/packages/universal/universal/src/reactive-core/into.ts +++ b/packages/universal/universal/src/reactive-core/into.ts @@ -1,10 +1,11 @@ import type { Description } from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; +import { intoReactive, isReactive } from "@starbeam/timeline"; import type { ReactiveBlueprint } from "./reactive.js"; -import { type Blueprint, type ReactiveFactory, Reactive } from "./reactive.js"; +import { type Blueprint, Reactive, type ReactiveFactory } from "./reactive.js"; import { ResourceBlueprint } from "./resource/resource.js"; -import { type ResourceFactory, Resource } from "./resource/resource.js"; +import { Resource, type ResourceFactory } from "./resource/resource.js"; export type IntoResource = | ResourceBlueprint @@ -50,7 +51,7 @@ function resource( description?: Description | string ): Reactive { const desc = Desc("resource", description); - return Reactive.from( + return intoReactive( IntoResource(create as IntoResource, desc).create(owner) ) as Reactive; } @@ -65,7 +66,7 @@ function createReactiveObject>(create: T): T; function createReactiveObject( create: IntoReactiveObject | Reactive ): unknown { - if (Reactive.is(create)) { + if (isReactive(create)) { return create; } else { return IntoReactiveObject(create).create(); diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index 4411ee99..26aeb209 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -1,6 +1,6 @@ import { Desc, type Description } from "@starbeam/debug"; -import type { ReactiveValue,Tag } from "@starbeam/interfaces"; -import { Reactive as TimelineReactive } from "@starbeam/timeline"; +import type { ReactiveValue, Tag } from "@starbeam/interfaces"; +import type * as interfaces from "@starbeam/interfaces"; import { isObject } from "@starbeam/verify"; import type { ResourceBlueprint } from "./resource/resource.js"; @@ -19,25 +19,11 @@ export function Reactive( return new ReactiveBlueprint(constructor, desc); } -Reactive.is = TimelineReactive.is; -Reactive.from = TimelineReactive.from; +export type IntoReactive = interfaces.Reactive | T; -Reactive.read = (value: IntoReactive): T => { - if (Reactive.is(value)) { - return value.current; - } else { - return value; - } -}; - -export type IntoReactive = Reactive | T; - -export type TypedReactive< - T, - I extends Tag = Tag -> = ReactiveValue; +export type TypedReactive = ReactiveValue; -export type Reactive = TimelineReactive; +export type Reactive = interfaces.Reactive; export class ReactiveBlueprint { static is(value: T | ReactiveBlueprint): value is ReactiveBlueprint { diff --git a/packages/universal/universal/src/reactive-core/resource/resource.ts b/packages/universal/universal/src/reactive-core/resource/resource.ts index 865323c4..708b78c4 100644 --- a/packages/universal/universal/src/reactive-core/resource/resource.ts +++ b/packages/universal/universal/src/reactive-core/resource/resource.ts @@ -14,15 +14,14 @@ */ import { Desc, type Description } from "@starbeam/debug"; +import type { Reactive } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import type { Reactive } from "@starbeam/timeline"; -import { LIFETIME } from "@starbeam/timeline"; +import { LIFETIME, Static } from "@starbeam/timeline"; import { isWeakKey } from "@starbeam/verify"; import { Formula } from "../formula/formula.js"; import type { IntoResource } from "../into.js"; import { type Blueprint, ReactiveBlueprint } from "../reactive.js"; -import { Static } from "../static.js"; import type { ResourceRun } from "./run.js"; import { ResourceState } from "./state.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts index 28f89402..1cc9509d 100644 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ b/packages/universal/universal/src/reactive-core/resource/state.ts @@ -1,9 +1,9 @@ import type { Description } from "@starbeam/debug"; +import type { Reactive } from "@starbeam/interfaces"; import { UNINITIALIZED } from "@starbeam/shared"; -import { LIFETIME, Reactive } from "@starbeam/timeline"; +import { isReactive, LIFETIME, Static } from "@starbeam/timeline"; import { Formula } from "../formula/formula.js"; -import { Static } from "../static.js"; import { type AssimilatedResourceReturn, brandResource, @@ -164,17 +164,19 @@ export class ResourceState { if (isResource(resource)) { LIFETIME.link(nextRun, resource, { root: this.#owner }); return resource as AssimilatedResourceReturn; - } else if (Reactive.is(resource)) { + } else if (isReactive(resource)) { return resource as AssimilatedResourceReturn; } else if (resource instanceof ResourceBlueprint) { return resource.use(nextRun, this) as AssimilatedResourceReturn; } else if (resource === UNINITIALIZED) { - return Static(undefined) as AssimilatedResourceReturn; + return Static( + undefined + ) as Reactive as AssimilatedResourceReturn; } else { return Static( resource, desc.detail("return") - ) as AssimilatedResourceReturn; + ) as Reactive as AssimilatedResourceReturn; } } } diff --git a/packages/universal/universal/src/reactive-core/service.ts b/packages/universal/universal/src/reactive-core/service.ts index 6037c35a..4072842b 100644 --- a/packages/universal/universal/src/reactive-core/service.ts +++ b/packages/universal/universal/src/reactive-core/service.ts @@ -2,7 +2,7 @@ import { Desc } from "@starbeam/debug"; import type { Description, Reactive } from "@starbeam/interfaces"; import { CONTEXT } from "@starbeam/timeline"; -import { type IntoResource, Factory } from "./into.js"; +import { Factory, type IntoResource } from "./into.js"; import type { Blueprint } from "./reactive.js"; import type { ResourceFactory } from "./resource/resource.js"; diff --git a/packages/universal/universal/src/reactive-core/static.ts b/packages/universal/universal/src/reactive-core/static.ts deleted file mode 100644 index d37029cd..00000000 --- a/packages/universal/universal/src/reactive-core/static.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Description } from "@starbeam/debug"; -import { Desc } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; -import { StaticTag } from "@starbeam/tags"; - -export function Static( - value: T, - description?: string | Description -): Reactive { - return Object.freeze({ - [TAG]: StaticTag.create(Desc("static", description)), - current: value, - read: () => value, - }); -} diff --git a/packages/universal/universal/tests/custom.spec.ts b/packages/universal/universal/tests/custom.spec.ts index 2d59754b..141dbef9 100644 --- a/packages/universal/universal/tests/custom.spec.ts +++ b/packages/universal/universal/tests/custom.spec.ts @@ -1,5 +1,6 @@ -import type { CustomBlueprint } from "@starbeam/universal"; -import { type IntoReactive, Reactive } from "@starbeam/universal"; +import { intoReactive, read } from "@starbeam/timeline"; +import type { CustomBlueprint, Reactive } from "@starbeam/universal"; +import { type IntoReactive } from "@starbeam/universal"; import { Cell, Custom, Formula } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -43,7 +44,7 @@ describe("Custom reactive objects", () => { return Custom(() => { const formatter = Formula( () => - new Intl.DateTimeFormat(Reactive.read(locale), { + new Intl.DateTimeFormat(read(locale), { year: "numeric", month: "long", day: "numeric", @@ -51,7 +52,7 @@ describe("Custom reactive objects", () => { ); return Formula(() => { - return formatter().format(Reactive.read(date)); + return formatter().format(read(date)); }); }); } @@ -77,7 +78,7 @@ describe("Custom reactive objects", () => { return Custom(() => { const age = Cell(0); return { - name: Reactive.from(name), + name: intoReactive(name), get age() { return age.current; @@ -152,7 +153,7 @@ class GenericImpl { readonly #age = Cell(0); constructor(name: IntoReactive) { - this.#name = Reactive.from(name); + this.#name = intoReactive(name); } get name(): S { diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index 33fe5591..27548572 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,7 +1,7 @@ import { entryPointFn } from "@starbeam/debug"; import { describeTagged } from "@starbeam/tags"; -import { Frame } from "@starbeam/timeline"; -import { Cell, FormulaValidation, Reactive, Static } from "@starbeam/universal"; +import { Frame, Static } from "@starbeam/timeline"; +import { Cell, FormulaValidation, Reactive } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; describe("reactive Factory", () => { diff --git a/packages/x/devtool/package.json b/packages/x/devtool/package.json index 61965b7f..0748d80a 100644 --- a/packages/x/devtool/package.json +++ b/packages/x/devtool/package.json @@ -32,9 +32,10 @@ "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/timeline": "workspace:^", "@starbeam/verify": "workspace:^", - "preact": "^10.11.3" + "preact": "^10.13.1" }, "devDependencies": { "@starbeam-dev/build-support": "workspace:*" diff --git a/packages/x/devtool/src/single/single-reactive.tsx b/packages/x/devtool/src/single/single-reactive.tsx index 38e24888..cb4b6e3d 100644 --- a/packages/x/devtool/src/single/single-reactive.tsx +++ b/packages/x/devtool/src/single/single-reactive.tsx @@ -5,24 +5,26 @@ import type { DebugOperation, Description, } from "@starbeam/debug"; -import type { MutableInternals } from "@starbeam/interfaces"; -import { ReactiveProtocol, TIMELINE } from "@starbeam/timeline"; +import type { CellTag } from "@starbeam/interfaces"; +import { getTag } from "@starbeam/tags"; +import { taggedDescription } from "@starbeam/tags"; +import { type Tagged, TIMELINE } from "@starbeam/timeline"; import { isPresent, verified } from "@starbeam/verify"; import { type JSX, render } from "preact"; export function DevtoolsFor(props: { - reactive: ReactiveProtocol; + reactive: Tagged; log: DebugOperation[]; }): JSX.Element { - function computeDependencies(): Iterable { - return ReactiveProtocol.dependencies(props.reactive); + function computeDependencies(): Iterable { + return getTag(props.reactive).dependencies(); } - function computeInvalidated(): MutableInternals[] { + function computeInvalidated(): CellTag[] { return props.log .map((operation) => operation.for) .filter( - (value): value is MutableInternals => + (value): value is CellTag => value !== undefined && value.type === "cell" ); } @@ -38,7 +40,7 @@ export function DevtoolsFor(props: {
  • description - {ReactiveProtocol.description(props.reactive).fullName} + {taggedDescription(props.reactive).fullName}
  • @@ -102,7 +104,7 @@ function Dependency({ ); } -function unique(dependencies: MutableInternals[]): Description[] { +function unique(dependencies: CellTag[]): Description[] { const descriptions = new Set( dependencies.map((d) => d.description.userFacing) ); @@ -111,16 +113,16 @@ function unique(dependencies: MutableInternals[]): Description[] { } export default function DevtoolsPane( - renderable: ReactiveProtocol, + renderable: Tagged, log: DebugOperation[], into: Element -): { update: (reactive: ReactiveProtocol, log: DebugOperation[]) => void } { +): { update: (reactive: Tagged, log: DebugOperation[]) => void } { const app = ; render(app, into); return { - update: (reactive: ReactiveProtocol, log: DebugOperation[]) => { + update: (reactive: Tagged, log: DebugOperation[]) => { render(, into); }, }; @@ -128,8 +130,7 @@ export default function DevtoolsPane( export function DevTools( listener: DebugListener, - - reactive: ReactiveProtocol + reactive: Tagged ): () => void { const pane = DevtoolsPane( reactive, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7ba04a15..1190f0b6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -891,6 +891,7 @@ importers: '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/tags': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/verify': workspace:^ preact: ^10.11.3 @@ -898,6 +899,7 @@ importers: '@starbeam/core-utils': link:../../universal/core-utils '@starbeam/debug': link:../../universal/debug '@starbeam/interfaces': link:../../universal/interfaces + '@starbeam/tags': link:../../universal/tags '@starbeam/timeline': link:../../universal/timeline '@starbeam/verify': link:../../universal/verify preact: 10.11.3 From c0dc1b320482050e81c3f96c5b9903f8f3676e66 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 24 Mar 2023 16:32:00 -0700 Subject: [PATCH 07/46] Start defining @starbeam/reactive --- packages/preact/preact/package.json | 1 + packages/preact/preact/src/options.ts | 3 +- packages/react/react/package.json | 1 + packages/react/react/src/use-setup.ts | 2 +- packages/react/react/tests/package.json | 1 + .../react/react/tests/use-resource.spec.ts | 2 +- packages/universal/reactive/.eslintrc.json | 12 +++++ packages/universal/reactive/.npmrc | 2 + packages/universal/reactive/index.ts | 2 + packages/universal/reactive/package.json | 28 ++++++++++++ packages/universal/reactive/rollup.config.mjs | 3 ++ .../universal/reactive/src/primitives/cell.ts | 45 +++++++++++++++++++ .../reactive/src/primitives/shared.ts | 5 +++ .../reactive/src/primitives/static.ts | 37 +++++++++++++++ packages/universal/reactive/src/runtime.ts | 26 +++++++++++ .../reactive.ts => reactive/src/utils.ts} | 35 ++------------- packages/universal/reactive/tsconfig.json | 12 +++++ packages/universal/timeline/index.ts | 6 --- packages/universal/universal/package.json | 1 + .../universal/src/reactive-core/into.ts | 2 +- .../src/reactive-core/resource/resource.ts | 3 +- .../src/reactive-core/resource/run.ts | 4 +- .../src/reactive-core/resource/state.ts | 10 ++--- .../universal/universal/tests/custom.spec.ts | 2 +- .../universal/universal/tests/factory.spec.ts | 3 +- pnpm-lock.yaml | 23 ++++++++++ 26 files changed, 219 insertions(+), 52 deletions(-) create mode 100644 packages/universal/reactive/.eslintrc.json create mode 100644 packages/universal/reactive/.npmrc create mode 100644 packages/universal/reactive/index.ts create mode 100644 packages/universal/reactive/package.json create mode 100644 packages/universal/reactive/rollup.config.mjs create mode 100644 packages/universal/reactive/src/primitives/cell.ts create mode 100644 packages/universal/reactive/src/primitives/shared.ts create mode 100644 packages/universal/reactive/src/primitives/static.ts create mode 100644 packages/universal/reactive/src/runtime.ts rename packages/universal/{timeline/src/utils/reactive.ts => reactive/src/utils.ts} (60%) create mode 100644 packages/universal/reactive/tsconfig.json diff --git a/packages/preact/preact/package.json b/packages/preact/preact/package.json index 16f8776e..d8a28214 100644 --- a/packages/preact/preact/package.json +++ b/packages/preact/preact/package.json @@ -40,6 +40,7 @@ "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/preact-utils": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/timeline": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" diff --git a/packages/preact/preact/src/options.ts b/packages/preact/preact/src/options.ts index 01294622..be7c155a 100644 --- a/packages/preact/preact/src/options.ts +++ b/packages/preact/preact/src/options.ts @@ -4,7 +4,8 @@ import type { InternalElement, } from "@starbeam/preact-utils"; import { Plugin } from "@starbeam/preact-utils"; -import { CONTEXT, isReactive, LIFETIME } from "@starbeam/timeline"; +import { isReactive } from "@starbeam/reactive"; +import { CONTEXT, LIFETIME } from "@starbeam/timeline"; import type { ComponentType } from "preact"; import { ComponentFrame } from "./frame.js"; diff --git a/packages/react/react/package.json b/packages/react/react/package.json index b4c46555..082b283b 100644 --- a/packages/react/react/package.json +++ b/packages/react/react/package.json @@ -33,6 +33,7 @@ "@starbeam/interfaces": "workspace:^", "@starbeam/js": "workspace:^", "@starbeam/modifier": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/timeline": "workspace:^", "@starbeam/universal": "workspace:^", diff --git a/packages/react/react/src/use-setup.ts b/packages/react/react/src/use-setup.ts index 46221ffb..924233b0 100644 --- a/packages/react/react/src/use-setup.ts +++ b/packages/react/react/src/use-setup.ts @@ -1,6 +1,6 @@ import { callerStack, Desc } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; -import { isReactive } from "@starbeam/timeline"; +import { isReactive } from "@starbeam/reactive"; import type { Reactive } from "@starbeam/universal"; import { PolledFormula } from "@starbeam/universal"; import { diff --git a/packages/react/react/tests/package.json b/packages/react/react/tests/package.json index cd3818fd..ee17fb22 100644 --- a/packages/react/react/tests/package.json +++ b/packages/react/react/tests/package.json @@ -11,6 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/react": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/timeline": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam-workspace/react-test-utils": "workspace:^", diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index 151d55b4..676656ea 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -3,7 +3,7 @@ import { entryPoint } from "@starbeam/debug"; import reactive from "@starbeam/js"; import { use, useProp, useReactive, useSetup } from "@starbeam/react"; -import { intoReactive } from "@starbeam/timeline"; +import { intoReactive } from "@starbeam/reactive"; import { Cell, Formula, diff --git a/packages/universal/reactive/.eslintrc.json b/packages/universal/reactive/.eslintrc.json new file mode 100644 index 00000000..c766d2c1 --- /dev/null +++ b/packages/universal/reactive/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/commonjs"], + "files": ["index.ts", "src/**/*.ts"], + "parserOptions": { + "project": "packages/universal/reactive/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/reactive/.npmrc b/packages/universal/reactive/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/reactive/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts new file mode 100644 index 00000000..dc4563f1 --- /dev/null +++ b/packages/universal/reactive/index.ts @@ -0,0 +1,2 @@ +export { Static } from "./src/primitives/static.js"; +export { intoReactive, isReactive, read } from "./src/utils.js"; diff --git a/packages/universal/reactive/package.json b/packages/universal/reactive/package.json new file mode 100644 index 00000000..e388bb63 --- /dev/null +++ b/packages/universal/reactive/package.json @@ -0,0 +1,28 @@ +{ + "name": "@starbeam/reactive", + "types": "index.ts", + "publishConfig": { + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.cjs" + } + }, + "main": "dist/index.cjs", + "types": "dist/index.d.ts" + }, + "starbeam:type": "library:public", + "scripts": { + "test:types": "tsc -b" + }, + "dependencies": { + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/shared": "workspace:^", + "@starbeam/tags": "workspace:^" + }, + "devDependencies": { + "@starbeam-dev/build-support": "workspace:*" + } +} diff --git a/packages/universal/reactive/rollup.config.mjs b/packages/universal/reactive/rollup.config.mjs new file mode 100644 index 00000000..dc01dc49 --- /dev/null +++ b/packages/universal/reactive/rollup.config.mjs @@ -0,0 +1,3 @@ +import { Package } from "@starbeam-dev/build-support"; + +export default Package.config(import.meta); diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts new file mode 100644 index 00000000..c9bc9055 --- /dev/null +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -0,0 +1,45 @@ +import type * as Debug from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; +import type * as interfaces from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { CellTag } from "@starbeam/tags"; + +import { getRuntime } from "../runtime.js"; +import type { PrimitiveOptions } from "./shared.js"; + +export class CellImpl + implements interfaces.ReactiveValue +{ + static create = ( + value: T, + { description }: { description?: string | Debug.Description } = {} + ): CellImpl => { + return new CellImpl(value, Desc("static", description)); + }; + + readonly #value: T; + readonly [TAG]: interfaces.CellTag; + + private constructor(value: T, description: Debug.Description) { + this.#value = value; + this[TAG] = CellTag.create(description); + } + + get current(): T { + return this.#value; + } + + read(caller = getRuntime().callerStack()): T { + getRuntime().didConsumeCell(this, caller); + return this.#value; + } +} + +export const Cell = CellImpl.create; +export type Cell = CellImpl; + +export type Equality = (a: T, b: T) => boolean; + +export interface CellOptions extends PrimitiveOptions { + equals?: Equality; +} diff --git a/packages/universal/reactive/src/primitives/shared.ts b/packages/universal/reactive/src/primitives/shared.ts new file mode 100644 index 00000000..1fabd361 --- /dev/null +++ b/packages/universal/reactive/src/primitives/shared.ts @@ -0,0 +1,5 @@ +import type { Description } from "@starbeam/debug"; + +export interface PrimitiveOptions { + description?: string | Description; +} diff --git a/packages/universal/reactive/src/primitives/static.ts b/packages/universal/reactive/src/primitives/static.ts new file mode 100644 index 00000000..a63f7593 --- /dev/null +++ b/packages/universal/reactive/src/primitives/static.ts @@ -0,0 +1,37 @@ +import type * as Debug from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; +import type * as interfaces from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { StaticTag } from "@starbeam/tags"; + +import type { PrimitiveOptions } from "./shared.js"; + +export class StaticImpl + implements interfaces.ReactiveValue +{ + static create = ( + value: T, + { description }: PrimitiveOptions = {} + ): StaticImpl => { + return new StaticImpl(value, Desc("static", description)); + }; + + readonly #value: T; + readonly [TAG]: interfaces.StaticTag; + + private constructor(value: T, description: Debug.Description) { + this.#value = value; + this[TAG] = StaticTag.create(description); + } + + get current(): T { + return this.#value; + } + + read(): T { + return this.#value; + } +} + +export const Static = StaticImpl.create; +export type Static = StaticImpl; diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts new file mode 100644 index 00000000..1742914c --- /dev/null +++ b/packages/universal/reactive/src/runtime.ts @@ -0,0 +1,26 @@ +import type { CellTag, Stack, Tagged } from "@starbeam/interfaces"; + +export interface ReactiveRuntime { + didConsumeCell: (cell: Tagged, caller?: Stack) => void; + callerStack: () => Stack; +} + +export const CONTEXT = { + runtime: null as null | ReactiveRuntime, +}; + +export function defineRuntime(runtime: ReactiveRuntime): void { + CONTEXT.runtime = runtime; +} + +export function getRuntime(): ReactiveRuntime { + if (import.meta.env.DEV) { + if (CONTEXT.runtime === null) { + throw Error( + "@starbeam/reactive requires a reactive runtime, but no runtime was registered (did you try to use @starbeam/reactive without @starbeam/universal?)" + ); + } + } + + return CONTEXT.runtime as ReactiveRuntime; +} diff --git a/packages/universal/timeline/src/utils/reactive.ts b/packages/universal/reactive/src/utils.ts similarity index 60% rename from packages/universal/timeline/src/utils/reactive.ts rename to packages/universal/reactive/src/utils.ts index fa1b5807..e8539a95 100644 --- a/packages/universal/timeline/src/utils/reactive.ts +++ b/packages/universal/reactive/src/utils.ts @@ -2,7 +2,8 @@ import type * as Debug from "@starbeam/debug"; import { callerStack, Desc } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { StaticTag } from "@starbeam/tags"; + +import { Static } from "./primitives/static.js"; export type Reactive = interfaces.Reactive; @@ -44,40 +45,10 @@ export function intoReactive( if (isReactive(value)) { return value; } else { - return Static(value, Desc("static", description)); + return Static(value, { description: Desc("static", description) }); } } function hasRead(value: object): value is { read: () => T } { return "read" in value && typeof value.read === "function"; } - -export class StaticImpl - implements interfaces.ReactiveValue -{ - static create = ( - value: T, - description?: string | Debug.Description - ): StaticImpl => { - return new StaticImpl(value, Desc("static", description)); - }; - - readonly #value: T; - readonly [TAG]: interfaces.StaticTag; - - private constructor(value: T, description: Debug.Description) { - this.#value = value; - this[TAG] = StaticTag.create(description); - } - - get current(): T { - return this.#value; - } - - read(): T { - return this.#value; - } -} - -export const Static = StaticImpl.create; -export type Static = StaticImpl; diff --git a/packages/universal/reactive/tsconfig.json b/packages/universal/reactive/tsconfig.json new file mode 100644 index 00000000..4790a1ab --- /dev/null +++ b/packages/universal/reactive/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../dist/types", + "declarationMap": true, + "outDir": "../../../dist/packages", + "types": ["../../env"] + }, + "exclude": ["dist/**/*"] +} diff --git a/packages/universal/timeline/index.ts b/packages/universal/timeline/index.ts index 4ec06903..3074c236 100644 --- a/packages/universal/timeline/index.ts +++ b/packages/universal/timeline/index.ts @@ -21,12 +21,6 @@ export { Subscriptions, } from "./src/timeline/subscriptions.js"; export { diff } from "./src/timeline/utils.js"; -export { - intoReactive, - isReactive, - read, - Static, -} from "./src/utils/reactive.js"; export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; export { getTag, Timestamp } from "@starbeam/tags"; diff --git a/packages/universal/universal/package.json b/packages/universal/universal/package.json index 75740267..a8ea92d1 100644 --- a/packages/universal/universal/package.json +++ b/packages/universal/universal/package.json @@ -28,6 +28,7 @@ "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", "@starbeam/timeline": "workspace:^", diff --git a/packages/universal/universal/src/reactive-core/into.ts b/packages/universal/universal/src/reactive-core/into.ts index 5b55e63d..79c6ce44 100644 --- a/packages/universal/universal/src/reactive-core/into.ts +++ b/packages/universal/universal/src/reactive-core/into.ts @@ -1,6 +1,6 @@ import type { Description } from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; -import { intoReactive, isReactive } from "@starbeam/timeline"; +import { intoReactive, isReactive } from "@starbeam/reactive"; import type { ReactiveBlueprint } from "./reactive.js"; import { type Blueprint, Reactive, type ReactiveFactory } from "./reactive.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/resource.ts b/packages/universal/universal/src/reactive-core/resource/resource.ts index 708b78c4..5873732d 100644 --- a/packages/universal/universal/src/reactive-core/resource/resource.ts +++ b/packages/universal/universal/src/reactive-core/resource/resource.ts @@ -15,8 +15,9 @@ import { Desc, type Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; +import { Static } from "@starbeam/reactive"; import { UNINITIALIZED } from "@starbeam/shared"; -import { LIFETIME, Static } from "@starbeam/timeline"; +import { LIFETIME } from "@starbeam/timeline"; import { isWeakKey } from "@starbeam/verify"; import { Formula } from "../formula/formula.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/run.ts b/packages/universal/universal/src/reactive-core/resource/run.ts index c84ce80c..765a02ef 100644 --- a/packages/universal/universal/src/reactive-core/resource/run.ts +++ b/packages/universal/universal/src/reactive-core/resource/run.ts @@ -1,6 +1,6 @@ -import { type Description, Desc } from "@starbeam/debug"; +import { Desc, type Description } from "@starbeam/debug"; import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { type Unsubscribe, LIFETIME } from "@starbeam/timeline"; +import { LIFETIME, type Unsubscribe } from "@starbeam/timeline"; import type { Handler, Resource, ResourceBlueprint } from "./resource"; import type { ResourceState } from "./state.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts index 1cc9509d..fcc0dcc4 100644 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ b/packages/universal/universal/src/reactive-core/resource/state.ts @@ -1,7 +1,8 @@ import type { Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; +import { isReactive, Static } from "@starbeam/reactive"; import { UNINITIALIZED } from "@starbeam/shared"; -import { isReactive, LIFETIME, Static } from "@starbeam/timeline"; +import { LIFETIME } from "@starbeam/timeline"; import { Formula } from "../formula/formula.js"; import { @@ -173,10 +174,9 @@ export class ResourceState { undefined ) as Reactive as AssimilatedResourceReturn; } else { - return Static( - resource, - desc.detail("return") - ) as Reactive as AssimilatedResourceReturn; + return Static(resource, { + description: desc.detail("return"), + }) as Reactive as AssimilatedResourceReturn; } } } diff --git a/packages/universal/universal/tests/custom.spec.ts b/packages/universal/universal/tests/custom.spec.ts index 141dbef9..417c897a 100644 --- a/packages/universal/universal/tests/custom.spec.ts +++ b/packages/universal/universal/tests/custom.spec.ts @@ -1,4 +1,4 @@ -import { intoReactive, read } from "@starbeam/timeline"; +import { intoReactive, read } from "@starbeam/reactive"; import type { CustomBlueprint, Reactive } from "@starbeam/universal"; import { type IntoReactive } from "@starbeam/universal"; import { Cell, Custom, Formula } from "@starbeam/universal"; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index 27548572..6072e59d 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,6 +1,7 @@ import { entryPointFn } from "@starbeam/debug"; +import { Static } from "@starbeam/reactive"; import { describeTagged } from "@starbeam/tags"; -import { Frame, Static } from "@starbeam/timeline"; +import { Frame } from "@starbeam/timeline"; import { Cell, FormulaValidation, Reactive } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1190f0b6..821b767b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -407,6 +407,7 @@ importers: '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/preact-utils': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ @@ -417,6 +418,7 @@ importers: '@starbeam/core-utils': link:../../universal/core-utils '@starbeam/debug': link:../../universal/debug '@starbeam/preact-utils': link:../preact-utils + '@starbeam/reactive': link:../../universal/reactive '@starbeam/timeline': link:../../universal/timeline '@starbeam/universal': link:../../universal/universal '@starbeam/verify': link:../../universal/verify @@ -548,6 +550,7 @@ importers: '@starbeam/interfaces': workspace:^ '@starbeam/js': workspace:^ '@starbeam/modifier': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ @@ -563,6 +566,7 @@ importers: '@starbeam/interfaces': link:../../universal/interfaces '@starbeam/js': link:../../universal/js '@starbeam/modifier': link:../../universal/modifier + '@starbeam/reactive': link:../../universal/reactive '@starbeam/shared': link:../../universal/shared '@starbeam/timeline': link:../../universal/timeline '@starbeam/universal': link:../../universal/universal @@ -582,6 +586,7 @@ importers: '@starbeam-workspace/test-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/react': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ jsdom: ^21.1.1 @@ -592,6 +597,7 @@ importers: '@starbeam-workspace/test-utils': link:../../../universal/test-utils '@starbeam/debug': link:../../../universal/debug '@starbeam/react': link:.. + '@starbeam/reactive': link:../../../universal/reactive '@starbeam/timeline': link:../../../universal/timeline '@starbeam/universal': link:../../../universal/universal jsdom: 21.1.1 @@ -765,6 +771,21 @@ importers: '@domtree/flavors': link:../../../workspace/@domtree/flavors '@starbeam-dev/build-support': link:../../../workspace/build + packages/universal/reactive: + specifiers: + '@starbeam-dev/build-support': workspace:* + '@starbeam/debug': workspace:^ + '@starbeam/interfaces': workspace:^ + '@starbeam/shared': workspace:^ + '@starbeam/tags': workspace:^ + dependencies: + '@starbeam/debug': link:../debug + '@starbeam/interfaces': link:../interfaces + '@starbeam/shared': link:../shared + '@starbeam/tags': link:../tags + devDependencies: + '@starbeam-dev/build-support': link:../../../workspace/build + packages/universal/shared: specifiers: '@starbeam-dev/build-support': workspace:* @@ -840,6 +861,7 @@ importers: '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/tags': workspace:^ '@starbeam/timeline': workspace:^ @@ -848,6 +870,7 @@ importers: '@starbeam/core-utils': link:../core-utils '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces + '@starbeam/reactive': link:../reactive '@starbeam/shared': link:../shared '@starbeam/tags': link:../tags '@starbeam/timeline': link:../timeline From 36cda9e568395dfc91eca04bd9589c0eb8ad9241 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 24 Mar 2023 21:36:53 -0700 Subject: [PATCH 08/46] Extract Cell into `reactive` And start establishing a minimal Runtime concept (related to #87) --- packages/universal/core-utils/index.ts | 4 +- packages/universal/core-utils/src/object.ts | 31 +++ packages/universal/interfaces/index.d.ts | 1 + .../universal/interfaces/src/protocol.d.ts | 20 +- packages/universal/js/index.ts | 4 +- packages/universal/js/src/iterable.ts | 4 +- packages/universal/reactive/index.ts | 3 + packages/universal/reactive/package.json | 1 + .../universal/reactive/src/primitives/cell.ts | 48 ++++- packages/universal/reactive/src/runtime.ts | 17 +- packages/universal/tags/src/tag.ts | 4 +- .../universal/timeline/src/timeline/frames.ts | 2 +- packages/universal/universal/index.ts | 2 +- .../universal/src/reactive-core/cell.ts | 176 ------------------ .../reactive-core/higher-level/freshness.ts | 3 +- .../universal/src/reactive-core/marker.ts | 4 +- .../universal/src/reactive-core/variants.ts | 2 +- packages/universal/universal/src/runtime.ts | 44 +++++ .../universal/universal/tests/formula.spec.ts | 4 +- .../universal/tests/resource.spec.ts | 8 +- pnpm-lock.yaml | 2 + 21 files changed, 166 insertions(+), 218 deletions(-) delete mode 100644 packages/universal/universal/src/reactive-core/cell.ts create mode 100644 packages/universal/universal/src/runtime.ts diff --git a/packages/universal/core-utils/index.ts b/packages/universal/core-utils/index.ts index 923b1bd2..ca3fe6c9 100644 --- a/packages/universal/core-utils/index.ts +++ b/packages/universal/core-utils/index.ts @@ -25,8 +25,8 @@ export type { JsonValue, } from "./src/json.js"; export { isJSONObject, stringifyJSON } from "./src/json.js"; -export { isObject, objectHasKeys } from "./src/object.js"; -export { type Matcher, type TypedOverload, Overload } from "./src/overload.js"; +export { isObject, objectHasKeys, readonly } from "./src/object.js"; +export { type Matcher, Overload, type TypedOverload } from "./src/overload.js"; export { isEmptyMatch, matchPattern, Pattern } from "./src/regexp.js"; export { asIntIndex, diff --git a/packages/universal/core-utils/src/object.ts b/packages/universal/core-utils/src/object.ts index 7f89f431..ba782a8e 100644 --- a/packages/universal/core-utils/src/object.ts +++ b/packages/universal/core-utils/src/object.ts @@ -1,3 +1,5 @@ +import { getFirst } from "./array.js"; +import { isSingleItemArray } from "./array.js"; import { isPresentArray } from "./array.js"; export function isObject(value: unknown): value is object { @@ -7,3 +9,32 @@ export function isObject(value: unknown): value is object { export function objectHasKeys(object: object): boolean { return isPresentArray(Object.keys(object)); } + +type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; + +type WithReadonly = Expand< + Exclude & { + readonly [P in K]: T[P]; + } +>; + +export function readonly( + object: T, + key: K, + ...args: [] | [T[K]] +): WithReadonly { + if (isSingleItemArray(args)) { + Object.defineProperty(object, key, { + enumerable: true, + configurable: true, + writable: false, + value: getFirst(args), + }); + } else { + Object.defineProperty(object, key, { + writable: false, + }); + } + + return object as WithReadonly; +} diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 87724ca5..768ef0e5 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -37,6 +37,7 @@ export type { ReactiveCell, ReactiveId, ReactiveValue, + Runtime, SpecificTag, StaticTag, Tag, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 53e0a81a..a1fb2c96 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -32,9 +32,26 @@ export interface DefaultMatcher extends Partial> { export type Matcher = ExhaustiveMatcher | DefaultMatcher; +export interface Runtime { + callerStack: () => Stack; + didConsumeCell: (cell: Tagged, caller: Stack) => void; + bumpCell: (cell: CellTag, caller: Stack) => Timestamp; + creatingFrame: (description: Description) => ActiveRuntimeFrame; + updatingFrame: ( + description: Description, + frame: RuntimeFrame + ) => ActiveRuntimeFrame; +} + +export interface ActiveRuntimeFrame { + done: () => RuntimeFrame; +} + +export type RuntimeFrame = object; + export interface UpdateOptions { readonly stack: Stack; - readonly timeline: { bump: (tag: CellTag, caller: Stack) => Timestamp }; + readonly runtime: Runtime; } /** @@ -45,6 +62,7 @@ export interface CellTag extends AbstractTag, TagMethods { readonly type: "cell"; readonly lastUpdated: Timestamp; isFrozen?: () => boolean; + freeze: () => void; update: (options: UpdateOptions) => void; } diff --git a/packages/universal/js/index.ts b/packages/universal/js/index.ts index e701dccd..343e5b17 100644 --- a/packages/universal/js/index.ts +++ b/packages/universal/js/index.ts @@ -32,7 +32,7 @@ export const reactive = ( let cell: Cell | undefined = CELLS.get(this); if (!cell) { - cell = Cell(undefined, `@reactive ${String(key)}`); + cell = Cell(undefined, { description: `@reactive ${String(key)}` }); CELLS.set(this, cell); } @@ -43,7 +43,7 @@ export const reactive = ( let cell: Cell | undefined = CELLS.get(this); if (!cell) { - cell = Cell(undefined, `@reactive ${String(key)}`); + cell = Cell(undefined, { description: `@reactive ${String(key)}` }); CELLS.set(this, cell); } diff --git a/packages/universal/js/src/iterable.ts b/packages/universal/js/src/iterable.ts index 6ad7678b..687784b6 100644 --- a/packages/universal/js/src/iterable.ts +++ b/packages/universal/js/src/iterable.ts @@ -1,7 +1,7 @@ import type { Stack } from "@starbeam/debug"; -import { type Description, callerStack } from "@starbeam/debug"; +import { callerStack, type Description } from "@starbeam/debug"; import { UNINITIALIZED } from "@starbeam/shared"; -import { type Equality, Cell, Marker } from "@starbeam/universal"; +import { Cell, type Equality, Marker } from "@starbeam/universal"; class Entry { readonly #initialized: Cell; diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index dc4563f1..1973dcb2 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -1,2 +1,5 @@ +export type { CellOptions, Equality } from "./src/primitives/cell.js"; +export { Cell } from "./src/primitives/cell.js"; export { Static } from "./src/primitives/static.js"; +export { defineRuntime, getRuntime } from "./src/runtime.js"; export { intoReactive, isReactive, read } from "./src/utils.js"; diff --git a/packages/universal/reactive/package.json b/packages/universal/reactive/package.json index e388bb63..cb79b50c 100644 --- a/packages/universal/reactive/package.json +++ b/packages/universal/reactive/package.json @@ -17,6 +17,7 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index c9bc9055..b1d361e3 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -1,3 +1,4 @@ +import { readonly } from "@starbeam/core-utils"; import type * as Debug from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; @@ -12,34 +13,61 @@ export class CellImpl { static create = ( value: T, - { description }: { description?: string | Debug.Description } = {} + { description, equals = Object.is }: CellOptions = {} ): CellImpl => { - return new CellImpl(value, Desc("static", description)); + return new CellImpl(value, equals, Desc("static", description)); }; - readonly #value: T; - readonly [TAG]: interfaces.CellTag; + #value: T; + readonly #equals: Equality; + declare readonly [TAG]: interfaces.CellTag; - private constructor(value: T, description: Debug.Description) { + private constructor( + value: T, + equality: Equality, + description: Debug.Description + ) { this.#value = value; - this[TAG] = CellTag.create(description); + this.#equals = equality; + readonly(this, TAG, CellTag.create(description)); } get current(): T { - return this.#value; + return this.read(getRuntime().callerStack()); + } + + set current(value: T) { + this.set(value, getRuntime().callerStack()); } read(caller = getRuntime().callerStack()): T { getRuntime().didConsumeCell(this, caller); return this.#value; } + + set(value: T, caller = getRuntime().callerStack()) { + if (this.#equals(value, this.#value)) { + return false; + } + + this.#value = value; + this[TAG].update({ stack: caller, runtime: getRuntime() }); + } + + update(updater: (prev: T) => T, caller = getRuntime().callerStack()) { + this.set(updater(this.#value), caller); + } + + freeze(): void { + this[TAG].freeze(); + } } export const Cell = CellImpl.create; -export type Cell = CellImpl; +export type Cell = CellImpl; export type Equality = (a: T, b: T) => boolean; -export interface CellOptions extends PrimitiveOptions { - equals?: Equality; +export interface CellOptions extends PrimitiveOptions { + equals?: Equality; } diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index 1742914c..1b6a2669 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -1,19 +1,14 @@ -import type { CellTag, Stack, Tagged } from "@starbeam/interfaces"; - -export interface ReactiveRuntime { - didConsumeCell: (cell: Tagged, caller?: Stack) => void; - callerStack: () => Stack; -} +import type { Runtime } from "@starbeam/interfaces"; export const CONTEXT = { - runtime: null as null | ReactiveRuntime, -}; + runtime: null as null | Runtime, +}; -export function defineRuntime(runtime: ReactiveRuntime): void { +export function defineRuntime(runtime: Runtime): void { CONTEXT.runtime = runtime; } -export function getRuntime(): ReactiveRuntime { +export function getRuntime(): Runtime { if (import.meta.env.DEV) { if (CONTEXT.runtime === null) { throw Error( @@ -22,5 +17,5 @@ export function getRuntime(): ReactiveRuntime { } } - return CONTEXT.runtime as ReactiveRuntime; + return CONTEXT.runtime as Runtime; } diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index 75c896eb..f06251a3 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -105,12 +105,12 @@ export class CellTag extends Tag implements interfaces.CellTag { if (!this.#frozen) yield this; } - update({ timeline, stack }: UpdateOptions): void { + update({ runtime: timeline, stack }: UpdateOptions): void { if (this.#frozen) { throw TypeError("Cannot update frozen object"); } - this.#lastUpdated = timeline.bump(this, stack); + this.#lastUpdated = timeline.bumpCell(this, stack); } } diff --git a/packages/universal/timeline/src/timeline/frames.ts b/packages/universal/timeline/src/timeline/frames.ts index 3a8dbce0..21a44458 100644 --- a/packages/universal/timeline/src/timeline/frames.ts +++ b/packages/universal/timeline/src/timeline/frames.ts @@ -127,7 +127,7 @@ export class FrameStack { } /** @internal */ - end(frame: ActiveFrame, value: T): Frame { + end(frame: ActiveFrame, value: T): Frame { return this.#end(frame, value); } diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index a9aade7a..c3f5eb39 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -1,5 +1,4 @@ export { DEBUG_RENDERER } from "./src/debug-renderer.js"; -export { Cell, type Equality } from "./src/reactive-core/cell.js"; export { Custom, CustomBlueprint, @@ -54,4 +53,5 @@ export { Variants, type VariantType, } from "./src/reactive-core/variants.js"; +export { Cell, type Equality, Static } from "@starbeam/reactive"; export { LIFETIME, TAG, TIMELINE } from "@starbeam/timeline"; diff --git a/packages/universal/universal/src/reactive-core/cell.ts b/packages/universal/universal/src/reactive-core/cell.ts deleted file mode 100644 index b7a0efde..00000000 --- a/packages/universal/universal/src/reactive-core/cell.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { isObject } from "@starbeam/core-utils"; -import { - callerStack, - type Description, - descriptionFrom, - DisplayStruct, - type Stack, -} from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; -import type { ReactiveValue } from "@starbeam/interfaces"; -import { UNINITIALIZED } from "@starbeam/shared"; -import { CellTag } from "@starbeam/tags"; -import { TAG, TIMELINE } from "@starbeam/timeline"; - -export interface CellPolicy { - equals: (a: T, b: T) => boolean; - map: (value: T) => U; -} - -export type Equality = (a: T, b: T) => boolean; - -const INSPECT = Symbol.for("nodejs.util.inspect.custom"); - -export class ReactiveCell implements ReactiveValue { - static create( - value: T, - tag: CellTag, - equals: Equality = Object.is - ): ReactiveCell { - return new ReactiveCell(value, equals, tag); - } - - #value: T; - readonly #equals: Equality; - readonly [TAG]: CellTag; - - declare [INSPECT]: () => object; - - private constructor(value: T, equals: Equality, tag: CellTag) { - this.#value = value; - this.#equals = equals; - - this[TAG] = tag; - - if (import.meta.env.DEV) { - this[INSPECT] = (): object => { - const { description, lastUpdated } = this[TAG]; - - const desc = ` (${description.describe()})`; - - return DisplayStruct(`Cell${desc}`, { - value: this.#value, - updated: lastUpdated, - }); - }; - - Object.defineProperty(this, TAG, { - writable: false, - }); - - Object.defineProperty(this, "toString", { - enumerable: false, - configurable: true, - writable: true, - value: (): string => `Cell (${String(this.#value)})`, - }); - } - } - - freeze(): void { - this[TAG].freeze(); - } - - get current(): T { - return this.read(callerStack()); - } - - set current(value: T) { - this.#set(value, callerStack()); - } - - read(caller = callerStack()): T { - TIMELINE.didConsumeCell(this, caller); - return this.#value; - } - - /** - * Returns true if the value was updated, and false if the value was already present and equal to - * the new value. - */ - set(value: T, caller = callerStack()): boolean { - return this.#set(value, caller); - } - - update(updater: (prev: T) => T, caller = callerStack()): boolean { - return this.#set(updater(this.#value), caller); - } - - initialize(initializer: () => T, caller = callerStack()): T { - if (this.#value === UNINITIALIZED) { - this.#set(initializer(), caller); - } - - return this.#value; - } - - #set(value: T, caller: Stack): boolean { - if (this.#equals(this.#value, value)) { - return false; - } - - this.#value = value; - this[TAG].update({ timeline: TIMELINE, stack: caller }); - return true; - } -} - -const INITIAL_INTERNAL_FRAMES = 0; - -/** - * The `equals` parameter is used to determine whether a new value is equal to - * the current value. If `equals` returns `true` for a new value, the old value - * remains in the cell and the cell's timestamp doesn't advance. - * - * It defaults to `Object.is` (`===` except that `Object.is(NaN, NaN)` is - * `true`). - * */ - -export function Cell( - value: T, - description?: - | string - | { description?: string | Description; equals?: Equality } -): Cell { - let desc: Description; - let equals: Equality; - - if (typeof description === "string" || description === undefined) { - desc = normalize(description); - equals = Object.is; - } else { - desc = normalize(description.description); - equals = description.equals ?? Object.is; - } - - return ReactiveCell.create(value, CellTag.create(desc), equals); -} - -const CALLER_FRAME = 1; - -function normalize( - description: string | Description | undefined, - internal = INITIAL_INTERNAL_FRAMES -): Description { - if (typeof description === "string" || description === undefined) { - return descriptionFrom( - { - type: "cell", - api: { - package: "@starbeam/universal", - name: "Cell", - }, - fromUser: description, - }, - internal + CALLER_FRAME - ); - } - - return description; -} - -Cell.is = (value: unknown): value is Cell => { - return isObject(value) && value instanceof ReactiveCell; -}; - -export type Cell = ReactiveCell; diff --git a/packages/universal/universal/src/reactive-core/higher-level/freshness.ts b/packages/universal/universal/src/reactive-core/higher-level/freshness.ts index bdda90e8..8487bd77 100644 --- a/packages/universal/universal/src/reactive-core/higher-level/freshness.ts +++ b/packages/universal/universal/src/reactive-core/higher-level/freshness.ts @@ -1,6 +1,5 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; - -import { Cell } from "../cell.js"; +import { Cell } from "@starbeam/reactive"; const INITIAL_COUNT = 0; const INCREMENT_COUNT = 1; diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts index 3f2d780c..d60f01f9 100644 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ b/packages/universal/universal/src/reactive-core/marker.ts @@ -4,6 +4,8 @@ import type * as interfaces from "@starbeam/interfaces"; import { CellTag } from "@starbeam/tags"; import { TAG, TIMELINE } from "@starbeam/timeline"; +import { RUNTIME } from "../runtime.js"; + export class ReactiveMarker implements Tagged { static create(tag: CellTag): ReactiveMarker { return new ReactiveMarker(tag); @@ -30,7 +32,7 @@ export class ReactiveMarker implements Tagged { } update(caller: Stack): void { - this[TAG].update({ timeline: TIMELINE, stack: caller }); + this[TAG].update({ runtime: RUNTIME, stack: caller }); } } diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index 88cf0466..085a751c 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -5,13 +5,13 @@ import { descriptionFrom, DisplayStruct, } from "@starbeam/debug"; +import { Cell } from "@starbeam/reactive"; import { UNINITIALIZED } from "@starbeam/shared"; import { FormulaTag } from "@starbeam/tags"; import { DelegateTag } from "@starbeam/tags"; import type { Tagged } from "@starbeam/timeline"; import { TAG, TIMELINE } from "@starbeam/timeline"; -import { Cell } from "./cell.js"; import { Marker } from "./marker.js"; export class VariantGroups { diff --git a/packages/universal/universal/src/runtime.ts b/packages/universal/universal/src/runtime.ts new file mode 100644 index 00000000..57ea5a43 --- /dev/null +++ b/packages/universal/universal/src/runtime.ts @@ -0,0 +1,44 @@ +import { callerStack } from "@starbeam/debug"; +import type { + CellTag, + Runtime as IRuntime, + Stack, + Tagged, + Timestamp, +} from "@starbeam/interfaces"; +import { defineRuntime } from "@starbeam/reactive"; +import { TIMELINE } from "@starbeam/timeline"; + +type Timeline = typeof TIMELINE; + +class Runtime implements IRuntime { + static default(): Runtime { + return new Runtime(TIMELINE); + } + + static timeline(timeline: Timeline): Runtime { + return new Runtime(timeline); + } + + readonly #timeline: Timeline; + + private constructor(timeline: Timeline) { + this.#timeline = timeline; + } + + callerStack(): Stack { + return callerStack(); + } + + didConsumeCell(cell: Tagged, caller: Stack): void { + this.#timeline.didConsumeCell(cell, caller); + } + + bumpCell(cell: CellTag, caller: Stack): Timestamp { + return this.#timeline.bump(cell, caller); + } +} + +export const RUNTIME = Runtime.default(); + +defineRuntime(RUNTIME); diff --git a/packages/universal/universal/tests/formula.spec.ts b/packages/universal/universal/tests/formula.spec.ts index bd4311bd..e928ff17 100644 --- a/packages/universal/universal/tests/formula.spec.ts +++ b/packages/universal/universal/tests/formula.spec.ts @@ -17,8 +17,8 @@ describe("A reactive formula", () => { }); test("produces stable values if inputs don't change", () => { - const name = Cell("@tomdale", "name"); - const location = Cell("New York", "location"); + const name = Cell("@tomdale", { description: "name" }); + const location = Cell("New York", { description: "location" }); const card = Formula( () => ({ diff --git a/packages/universal/universal/tests/resource.spec.ts b/packages/universal/universal/tests/resource.spec.ts index 3817c1ef..31cc7110 100644 --- a/packages/universal/universal/tests/resource.spec.ts +++ b/packages/universal/universal/tests/resource.spec.ts @@ -15,11 +15,11 @@ import { } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; import { - type ResourceBlueprint, Cell, Formula, LIFETIME, Resource, + type ResourceBlueprint, Wrap, } from "@starbeam/universal"; import { exhaustive, verified } from "@starbeam/verify"; @@ -155,7 +155,7 @@ describe("use()", () => { return cell; }, "Inner"); - const counter = Cell(INITIAL_COUNT, "i"); + const counter = Cell(INITIAL_COUNT, { description: "i" }); let run = 0; let currentInstance = undefined as Reactive | undefined; let prevInner = undefined as Reactive | undefined; @@ -193,8 +193,8 @@ describe("use()", () => { test("transferring a resource prevents it from being cleaned up", () => { const { resource: inner } = TestResource("inner"); - const outerDep = Cell(INITIAL_COUNT, "OuterDep"); - const formulaDep = Cell(INITIAL_COUNT, "FormulaDep"); + const outerDep = Cell(INITIAL_COUNT, { description: "OuterDep" }); + const formulaDep = Cell(INITIAL_COUNT, { description: "FormulaDep" }); const Outer = Resource(({ use, on }) => { const innerValue = use(inner); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 821b767b..be9f0c69 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -774,11 +774,13 @@ importers: packages/universal/reactive: specifiers: '@starbeam-dev/build-support': workspace:* + '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/tags': workspace:^ dependencies: + '@starbeam/core-utils': link:../core-utils '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces '@starbeam/shared': link:../shared From 5430b0607daebd22434c88da0e7b7224d9d6c304 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 25 Mar 2023 17:13:49 -0700 Subject: [PATCH 09/46] Rename timeline to runtime Getting close to a new runtime foundation! --- .../rollup-plugin-polyfill-node/tsconfig.json | 4 +- demos/preact-hello-world/package.json | 2 +- demos/react-jsnation/package.json | 1 + package.json | 3 +- .../preact-testing-utils/tests/package.json | 2 +- .../preact/preact-utils/tests/package.json | 2 +- packages/preact/preact/package.json | 10 +- packages/preact/preact/src/frame.ts | 2 +- packages/preact/preact/src/options.ts | 2 +- packages/preact/preact/tests/package.json | 2 +- packages/react/react/package.json | 2 +- packages/react/react/src/context-provider.ts | 2 +- packages/react/react/src/debug/warnings.ts | 2 +- packages/react/react/src/element.ts | 2 +- packages/react/react/src/use-resource.ts | 2 +- packages/react/react/src/use-service.ts | 2 +- packages/react/react/tests/package.json | 2 +- packages/react/react/tests/support/channel.ts | 2 +- packages/universal/core-utils/index.ts | 4 +- packages/universal/core-utils/src/iterable.ts | 7 ++ packages/universal/interfaces/index.d.ts | 1 + .../universal/interfaces/src/protocol.d.ts | 26 +--- .../universal/interfaces/src/runtime.d.ts | 34 ++++++ packages/universal/js/package.json | 2 +- .../universal/reactive/src/primitives/cell.ts | 8 +- .../reactive/src/primitives/formula.ts | 23 ++++ .../reactive/src/primitives/marker.ts | 35 ++++++ .../{timeline => runtime}/.eslintrc.json | 2 +- .../universal/{timeline => runtime}/.npmrc | 0 .../{timeline => runtime}/CHANGELOG.md | 0 .../universal/{timeline => runtime}/README.md | 2 +- .../universal/{timeline => runtime}/index.ts | 0 .../{timeline => runtime}/package.json | 2 +- .../{timeline => runtime}/rollup.config.mjs | 0 .../src/context/context.ts | 0 .../{timeline => runtime}/src/lifetime/api.ts | 0 .../src/lifetime/object-lifetime.ts | 0 .../{timeline => runtime}/src/timeline/api.ts | 0 .../src/timeline/frame.ts | 0 .../src/timeline/frames.ts | 4 +- .../{timeline => runtime}/src/timeline/id.ts | 0 .../src/timeline/subscriptions.md | 0 .../src/timeline/subscriptions.ts | 33 ++--- .../src/timeline/timeline.ts | 4 +- .../universal/runtime/src/timeline/tracker.ts | 58 +++++++++ .../src/timeline/utils.ts | 0 .../universal/runtime/src/tracking-stack.ts | 46 +++++++ .../tests/.eslintrc.json | 2 +- .../{timeline => runtime}/tests/.npmrc | 0 .../{timeline => runtime}/tests/CHANGELOG.md | 0 .../tests/consume.spec.ts | 2 +- .../tests/lifetime.spec.ts | 2 +- .../{timeline => runtime}/tests/package.json | 2 +- .../tests/pollable.spec.ts | 2 +- .../tests/protocol.spec.ts | 2 +- .../tests/subscription.ts | 2 +- .../tests/support/mini-reactives.ts | 2 +- .../tests/support/testing.ts | 0 .../{timeline => runtime}/tests/tsconfig.json | 0 .../{timeline => runtime}/tsconfig.json | 0 packages/universal/test-utils/package.json | 2 +- packages/universal/universal/index.ts | 2 +- packages/universal/universal/package.json | 2 +- .../universal/universal/src/debug-renderer.ts | 4 +- .../universal/src/reactive-core/delegate.ts | 2 +- .../src/reactive-core/formula/formula.ts | 2 +- .../reactive-core/formula/polled-formula.ts | 2 +- .../src/reactive-core/formula/setups.ts | 2 +- .../universal/src/reactive-core/marker.ts | 2 +- .../src/reactive-core/resource/resource.ts | 2 +- .../src/reactive-core/resource/run.ts | 2 +- .../src/reactive-core/resource/state.ts | 2 +- .../universal/src/reactive-core/service.ts | 2 +- .../universal/src/reactive-core/variants.ts | 4 +- packages/universal/universal/src/runtime.ts | 2 +- .../universal/universal/tests/factory.spec.ts | 2 +- .../universal/universal/tests/package.json | 2 +- .../universal/universal/tests/setup.spec.ts | 2 +- .../universal/tests/variants.spec.ts | 2 +- packages/x/devtool/package.json | 2 +- packages/x/devtool/src/log/frame.tsx | 2 +- packages/x/devtool/src/log/log.tsx | 2 +- packages/x/devtool/src/log/ui.tsx | 2 +- .../x/devtool/src/single/single-reactive.tsx | 2 +- packages/x/vanilla/package.json | 2 +- packages/x/vanilla/src/dom.ts | 2 +- pnpm-lock.yaml | 114 +++++++++--------- workspace/@domtree/any/package.json | 4 + workspace/@domtree/browser/package.json | 4 + workspace/@domtree/flavors/package.json | 4 + workspace/@domtree/interface/package.json | 4 + workspace/@domtree/minimal/package.json | 4 + 92 files changed, 367 insertions(+), 176 deletions(-) create mode 100644 packages/universal/interfaces/src/runtime.d.ts create mode 100644 packages/universal/reactive/src/primitives/formula.ts create mode 100644 packages/universal/reactive/src/primitives/marker.ts rename packages/universal/{timeline => runtime}/.eslintrc.json (73%) rename packages/universal/{timeline => runtime}/.npmrc (100%) rename packages/universal/{timeline => runtime}/CHANGELOG.md (100%) rename packages/universal/{timeline => runtime}/README.md (99%) rename packages/universal/{timeline => runtime}/index.ts (100%) rename packages/universal/{timeline => runtime}/package.json (96%) rename packages/universal/{timeline => runtime}/rollup.config.mjs (100%) rename packages/universal/{timeline => runtime}/src/context/context.ts (100%) rename packages/universal/{timeline => runtime}/src/lifetime/api.ts (100%) rename packages/universal/{timeline => runtime}/src/lifetime/object-lifetime.ts (100%) rename packages/universal/{timeline => runtime}/src/timeline/api.ts (100%) rename packages/universal/{timeline => runtime}/src/timeline/frame.ts (100%) rename packages/universal/{timeline => runtime}/src/timeline/frames.ts (97%) rename packages/universal/{timeline => runtime}/src/timeline/id.ts (100%) rename packages/universal/{timeline => runtime}/src/timeline/subscriptions.md (100%) rename packages/universal/{timeline => runtime}/src/timeline/subscriptions.ts (89%) rename packages/universal/{timeline => runtime}/src/timeline/timeline.ts (97%) create mode 100644 packages/universal/runtime/src/timeline/tracker.ts rename packages/universal/{timeline => runtime}/src/timeline/utils.ts (100%) create mode 100644 packages/universal/runtime/src/tracking-stack.ts rename packages/universal/{timeline => runtime}/tests/.eslintrc.json (69%) rename packages/universal/{timeline => runtime}/tests/.npmrc (100%) rename packages/universal/{timeline => runtime}/tests/CHANGELOG.md (100%) rename packages/universal/{timeline => runtime}/tests/consume.spec.ts (97%) rename packages/universal/{timeline => runtime}/tests/lifetime.spec.ts (99%) rename packages/universal/{timeline => runtime}/tests/package.json (89%) rename packages/universal/{timeline => runtime}/tests/pollable.spec.ts (98%) rename packages/universal/{timeline => runtime}/tests/protocol.spec.ts (98%) rename packages/universal/{timeline => runtime}/tests/subscription.ts (97%) rename packages/universal/{timeline => runtime}/tests/support/mini-reactives.ts (97%) rename packages/universal/{timeline => runtime}/tests/support/testing.ts (100%) rename packages/universal/{timeline => runtime}/tests/tsconfig.json (100%) rename packages/universal/{timeline => runtime}/tsconfig.json (100%) diff --git a/@types/rollup-plugin-polyfill-node/tsconfig.json b/@types/rollup-plugin-polyfill-node/tsconfig.json index 8ae187c2..e5c0a262 100644 --- a/@types/rollup-plugin-polyfill-node/tsconfig.json +++ b/@types/rollup-plugin-polyfill-node/tsconfig.json @@ -2,9 +2,9 @@ "extends": "../../.config/tsconfig/tsconfig.shared.json", "compilerOptions": { "declarationMap": true, - "declarationDir": "../../../dist/types", + "declarationDir": "../../dist/types", "declaration": true, - "outDir": "../../../dist/packages", + "outDir": "../../dist/packages", "composite": true, "types": ["../../packages/env"] }, diff --git a/demos/preact-hello-world/package.json b/demos/preact-hello-world/package.json index 8cb076a4..7ee4c170 100644 --- a/demos/preact-hello-world/package.json +++ b/demos/preact-hello-world/package.json @@ -38,7 +38,7 @@ "dependencies": { "@starbeam/js": "workspace:^", "@starbeam/preact": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "preact": "^10.11.3", "purecss": "3.0.0" diff --git a/demos/react-jsnation/package.json b/demos/react-jsnation/package.json index 21d17f1e..637d93e1 100644 --- a/demos/react-jsnation/package.json +++ b/demos/react-jsnation/package.json @@ -48,6 +48,7 @@ "devDependencies": { "@types/react": "^18.0.26", "@types/react-dom": "^18.0.10", + "@vitest/ui": "*", "vite": "*", "vite-plugin-fonts": "^0.6.0" } diff --git a/package.json b/package.json index 8f7fb966..7edfcc96 100644 --- a/package.json +++ b/package.json @@ -177,6 +177,7 @@ } }, "volta": { - "node": "19.0.1" + "node": "19.8.1", + "pnpm": "7.30.3" } } diff --git a/packages/preact/preact-testing-utils/tests/package.json b/packages/preact/preact-testing-utils/tests/package.json index a39f99ff..7be1bf50 100644 --- a/packages/preact/preact-testing-utils/tests/package.json +++ b/packages/preact/preact-testing-utils/tests/package.json @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/preact": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam-workspace/preact-testing-utils": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", diff --git a/packages/preact/preact-utils/tests/package.json b/packages/preact/preact-utils/tests/package.json index 0cb3f17d..abb83fb1 100644 --- a/packages/preact/preact-utils/tests/package.json +++ b/packages/preact/preact-utils/tests/package.json @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/preact": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", "@testing-library/dom": "^8.19.1", diff --git a/packages/preact/preact/package.json b/packages/preact/preact/package.json index d8a28214..827710dc 100644 --- a/packages/preact/preact/package.json +++ b/packages/preact/preact/package.json @@ -5,8 +5,7 @@ "main": "index.ts", "types": "index.ts", "exports": { - ".": "./index.ts", - "./setup": "./src/setup.ts" + "default": "./index.ts" }, "publishConfig": { "exports": { @@ -14,11 +13,6 @@ "types": "./dist/index.d.ts", "import": "./dist/index.js", "default": "./dist/index.cjs" - }, - "./setup": { - "types": "./dist/setup.d.ts", - "import": "./dist/setup.js", - "default": "./dist/setup.cjs" } }, "main": "dist/index.cjs", @@ -41,7 +35,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/preact-utils": "workspace:^", "@starbeam/reactive": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index e952c140..813ffc07 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -6,7 +6,7 @@ import { type Frame, TIMELINE, type Unsubscribe, -} from "@starbeam/timeline"; +} from "@starbeam/runtime"; import { expected, isPresent, verify } from "@starbeam/verify"; export class ComponentFrame { diff --git a/packages/preact/preact/src/options.ts b/packages/preact/preact/src/options.ts index be7c155a..200b7a3f 100644 --- a/packages/preact/preact/src/options.ts +++ b/packages/preact/preact/src/options.ts @@ -5,7 +5,7 @@ import type { } from "@starbeam/preact-utils"; import { Plugin } from "@starbeam/preact-utils"; import { isReactive } from "@starbeam/reactive"; -import { CONTEXT, LIFETIME } from "@starbeam/timeline"; +import { CONTEXT, LIFETIME } from "@starbeam/runtime"; import type { ComponentType } from "preact"; import { ComponentFrame } from "./frame.js"; diff --git a/packages/preact/preact/tests/package.json b/packages/preact/preact/tests/package.json index e18a4f2b..742b5c7e 100644 --- a/packages/preact/preact/tests/package.json +++ b/packages/preact/preact/tests/package.json @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/preact": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam-workspace/preact-testing-utils": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", diff --git a/packages/react/react/package.json b/packages/react/react/package.json index 082b283b..5c6e45b0 100644 --- a/packages/react/react/package.json +++ b/packages/react/react/package.json @@ -34,8 +34,8 @@ "@starbeam/js": "workspace:^", "@starbeam/modifier": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/shared": "workspace:^", - "@starbeam/timeline": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/use-strict-lifecycle": "workspace:^", "@starbeam/verify": "workspace:^" diff --git a/packages/react/react/src/context-provider.ts b/packages/react/react/src/context-provider.ts index 2507c371..fad93876 100644 --- a/packages/react/react/src/context-provider.ts +++ b/packages/react/react/src/context-provider.ts @@ -1,4 +1,4 @@ -import { LIFETIME } from "@starbeam/timeline"; +import { LIFETIME } from "@starbeam/runtime"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; import type { FunctionComponent } from "react"; import { diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index ff3fb271..a637943d 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,5 +1,5 @@ import { Message } from "@starbeam/debug"; -import { TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "@starbeam/runtime"; import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 700475df..06891d6d 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -7,7 +7,7 @@ import { type OnCleanup, TIMELINE, type Unsubscribe, -} from "@starbeam/timeline"; +} from "@starbeam/runtime"; import { type Cell, createService, diff --git a/packages/react/react/src/use-resource.ts b/packages/react/react/src/use-resource.ts index 8a771643..e49a5e5b 100644 --- a/packages/react/react/src/use-resource.ts +++ b/packages/react/react/src/use-resource.ts @@ -1,5 +1,5 @@ import { Desc, type Description } from "@starbeam/debug"; -import { LIFETIME, TIMELINE } from "@starbeam/timeline"; +import { LIFETIME, TIMELINE } from "@starbeam/runtime"; import { Cell, Factory, diff --git a/packages/react/react/src/use-service.ts b/packages/react/react/src/use-service.ts index 093285a5..5190097a 100644 --- a/packages/react/react/src/use-service.ts +++ b/packages/react/react/src/use-service.ts @@ -1,4 +1,4 @@ -import { CONTEXT } from "@starbeam/timeline"; +import { CONTEXT } from "@starbeam/runtime"; import { type Blueprint, type ResourceFactory, diff --git a/packages/react/react/tests/package.json b/packages/react/react/tests/package.json index ee17fb22..cef7c008 100644 --- a/packages/react/react/tests/package.json +++ b/packages/react/react/tests/package.json @@ -12,7 +12,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/reactive": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam-workspace/react-test-utils": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", diff --git a/packages/react/react/tests/support/channel.ts b/packages/react/react/tests/support/channel.ts index 8a9bac7f..25a87f82 100644 --- a/packages/react/react/tests/support/channel.ts +++ b/packages/react/react/tests/support/channel.ts @@ -1,5 +1,5 @@ import { getLast, removeItem } from "@starbeam/core-utils"; -import type { Unsubscribe } from "@starbeam/timeline"; +import type { Unsubscribe } from "@starbeam/runtime"; const FIRST_ID = 0; diff --git a/packages/universal/core-utils/index.ts b/packages/universal/core-utils/index.ts index ca3fe6c9..a9b61381 100644 --- a/packages/universal/core-utils/index.ts +++ b/packages/universal/core-utils/index.ts @@ -1,4 +1,4 @@ -export { + export { firstNItems, getFirst, getLast, @@ -17,7 +17,7 @@ export { zipArrays, } from "./src/array.js"; export { type UnknownFn } from "./src/function.js"; -export { reverse } from "./src/iterable.js"; +export { iterableHasItems, reverse } from "./src/iterable.js"; export type { JsonArray, JsonObject, diff --git a/packages/universal/core-utils/src/iterable.ts b/packages/universal/core-utils/src/iterable.ts index f2df72fc..1ba784c0 100644 --- a/packages/universal/core-utils/src/iterable.ts +++ b/packages/universal/core-utils/src/iterable.ts @@ -5,3 +5,10 @@ export function reverse(list: Iterable): T[]; export function reverse(list: Iterable): AnyArray { return [...list].reverse(); } + +export function iterableHasItems(list: PresentArray): true; +export function iterableHasItems(iterable: Iterable): boolean; +export function iterableHasItems(iterable: Iterable): boolean { + const iterator = iterable[Symbol.iterator](); + return !iterator.next().done; +} diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 768ef0e5..78783c27 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -35,6 +35,7 @@ export type { Matcher, Reactive, ReactiveCell, + ReactiveFormula, ReactiveId, ReactiveValue, Runtime, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index a1fb2c96..18951633 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -32,28 +32,6 @@ export interface DefaultMatcher extends Partial> { export type Matcher = ExhaustiveMatcher | DefaultMatcher; -export interface Runtime { - callerStack: () => Stack; - didConsumeCell: (cell: Tagged, caller: Stack) => void; - bumpCell: (cell: CellTag, caller: Stack) => Timestamp; - creatingFrame: (description: Description) => ActiveRuntimeFrame; - updatingFrame: ( - description: Description, - frame: RuntimeFrame - ) => ActiveRuntimeFrame; -} - -export interface ActiveRuntimeFrame { - done: () => RuntimeFrame; -} - -export type RuntimeFrame = object; - -export interface UpdateOptions { - readonly stack: Stack; - readonly runtime: Runtime; -} - /** * Cell is the fundamental mutable reactive value. All subscriptions in Starbeam are ultimately * subscriptions to cells, and all mutations in Starbeam are ultimately mutations to cells. @@ -157,3 +135,7 @@ export interface Reactive extends ReactiveValue { export interface ReactiveCell extends Reactive { current: T; } + +export interface ReactiveFormula extends Reactive { + readonly current: T; +} diff --git a/packages/universal/interfaces/src/runtime.d.ts b/packages/universal/interfaces/src/runtime.d.ts new file mode 100644 index 00000000..6687dd8b --- /dev/null +++ b/packages/universal/interfaces/src/runtime.d.ts @@ -0,0 +1,34 @@ +import type { Description } from "./description.js"; +import type { CellTag, Tagged } from "./protocol.js"; +import type { Stack as CallStack } from "./stack.js"; +import type { Timestamp } from "./timestamp.js"; + +export interface Runtime { + callerStack: () => CallStack; + didConsumeCell: (cell: Tagged, caller: CallStack) => void; + bumpCell: (cell: CellTag, caller: CallStack) => Timestamp; + creatingFrame: (description: Description) => ActiveRuntimeFrame; + updatingFrame: ( + description: Description, + frame: RuntimeFrame + ) => ActiveRuntimeFrame; +} + +export interface ActiveRuntimeFrame { + done: () => RuntimeFrame; +} + +export type RuntimeFrame = object; + +export interface UpdateOptions { + readonly caller: CallStack; + readonly runtime: Runtime; +} + +export interface TrackingStack { + start: () => TrackingFrame; +} + +export interface TrackingFrame { + done: () => Set; +} diff --git a/packages/universal/js/package.json b/packages/universal/js/package.json index 5d16828b..1f17b495 100644 --- a/packages/universal/js/package.json +++ b/packages/universal/js/package.json @@ -30,7 +30,7 @@ "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index b1d361e3..841b2c28 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -1,16 +1,14 @@ import { readonly } from "@starbeam/core-utils"; import type * as Debug from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; +import type { CellTag as ICellTag, ReactiveCell } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { CellTag } from "@starbeam/tags"; import { getRuntime } from "../runtime.js"; import type { PrimitiveOptions } from "./shared.js"; -export class CellImpl - implements interfaces.ReactiveValue -{ +export class CellImpl implements ReactiveCell { static create = ( value: T, { description, equals = Object.is }: CellOptions = {} @@ -20,7 +18,7 @@ export class CellImpl #value: T; readonly #equals: Equality; - declare readonly [TAG]: interfaces.CellTag; + declare readonly [TAG]: ICellTag; private constructor( value: T, diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts new file mode 100644 index 00000000..0634294f --- /dev/null +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -0,0 +1,23 @@ +import { readonly } from "@starbeam/core-utils"; +import type { + FormulaTag as IFormulaTag, + ReactiveFormula, + Stack, + Tag, +} from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { FormulaTag } from "@starbeam/tags"; +import type { Marker } from "./marker.js"; +import type { Description } from "@starbeam/debug"; + +class FormulaValue implements ReactiveFormula { + declare readonly [TAG]: Tag; + readonly #initialized: Marker; + + constructor(description: Description) { + this.#initialized = Marker(description.); + readonly(this, TAG, FormulaTag.create()); + } + + read: (stack?: Stack | undefined) => IFormulaTag; +} diff --git a/packages/universal/reactive/src/primitives/marker.ts b/packages/universal/reactive/src/primitives/marker.ts new file mode 100644 index 00000000..4a4c5aa0 --- /dev/null +++ b/packages/universal/reactive/src/primitives/marker.ts @@ -0,0 +1,35 @@ +import { readonly } from "@starbeam/core-utils"; +import { Desc, type Description } from "@starbeam/debug"; +import { type CellTag as ICellTag, type Tagged } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { CellTag } from "@starbeam/tags"; + +import { getRuntime } from "../runtime.js"; +import type { PrimitiveOptions } from "./shared.js"; + +class MarkerImpl implements Tagged { + static create(this: void, { description }: PrimitiveOptions): MarkerImpl { + return new MarkerImpl(Desc("cell", description)); + } + + declare readonly [TAG]: ICellTag; + + private constructor(description: Description) { + readonly(this, TAG, CellTag.create(description)); + } + + read(caller = getRuntime().callerStack()): void { + this[TAG].update({ stack: caller, runtime: getRuntime() }); + } + + freeze(): void { + this[TAG].freeze(); + } + + bump(caller = getRuntime().callerStack()): void { + this[TAG].update({ stack: caller, runtime: getRuntime() }); + } +} + +export const Marker = MarkerImpl.create; +export type Marker = MarkerImpl; diff --git a/packages/universal/timeline/.eslintrc.json b/packages/universal/runtime/.eslintrc.json similarity index 73% rename from packages/universal/timeline/.eslintrc.json rename to packages/universal/runtime/.eslintrc.json index 13bcd735..e680933b 100644 --- a/packages/universal/timeline/.eslintrc.json +++ b/packages/universal/runtime/.eslintrc.json @@ -5,7 +5,7 @@ "extends": ["plugin:@starbeam/tight"], "files": ["index.ts", "src/**/*.ts"], "parserOptions": { - "project": "packages/universal/timeline/tsconfig.json" + "project": "packages/universal/runtime/tsconfig.json" } } ] diff --git a/packages/universal/timeline/.npmrc b/packages/universal/runtime/.npmrc similarity index 100% rename from packages/universal/timeline/.npmrc rename to packages/universal/runtime/.npmrc diff --git a/packages/universal/timeline/CHANGELOG.md b/packages/universal/runtime/CHANGELOG.md similarity index 100% rename from packages/universal/timeline/CHANGELOG.md rename to packages/universal/runtime/CHANGELOG.md diff --git a/packages/universal/timeline/README.md b/packages/universal/runtime/README.md similarity index 99% rename from packages/universal/timeline/README.md rename to packages/universal/runtime/README.md index 11a400df..6dcc14c7 100644 --- a/packages/universal/timeline/README.md +++ b/packages/universal/runtime/README.md @@ -94,7 +94,7 @@ You can specify a custom `Coordinator` to use an alternative strategy. For examp Finally, you can also explicitly schedule a _Render_ phase, which will supersede the `Coordinator`'s policy and simply wait until you're ready to render. ```ts -import { TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "@starbeam/runtime"; import { Cell } from "@starbeam/reactive"; const person = reactive({ diff --git a/packages/universal/timeline/index.ts b/packages/universal/runtime/index.ts similarity index 100% rename from packages/universal/timeline/index.ts rename to packages/universal/runtime/index.ts diff --git a/packages/universal/timeline/package.json b/packages/universal/runtime/package.json similarity index 96% rename from packages/universal/timeline/package.json rename to packages/universal/runtime/package.json index 5d4391a7..3017e4b7 100644 --- a/packages/universal/timeline/package.json +++ b/packages/universal/runtime/package.json @@ -1,5 +1,5 @@ { - "name": "@starbeam/timeline", + "name": "@starbeam/runtime", "version": "0.8.9", "type": "module", "main": "index.ts", diff --git a/packages/universal/timeline/rollup.config.mjs b/packages/universal/runtime/rollup.config.mjs similarity index 100% rename from packages/universal/timeline/rollup.config.mjs rename to packages/universal/runtime/rollup.config.mjs diff --git a/packages/universal/timeline/src/context/context.ts b/packages/universal/runtime/src/context/context.ts similarity index 100% rename from packages/universal/timeline/src/context/context.ts rename to packages/universal/runtime/src/context/context.ts diff --git a/packages/universal/timeline/src/lifetime/api.ts b/packages/universal/runtime/src/lifetime/api.ts similarity index 100% rename from packages/universal/timeline/src/lifetime/api.ts rename to packages/universal/runtime/src/lifetime/api.ts diff --git a/packages/universal/timeline/src/lifetime/object-lifetime.ts b/packages/universal/runtime/src/lifetime/object-lifetime.ts similarity index 100% rename from packages/universal/timeline/src/lifetime/object-lifetime.ts rename to packages/universal/runtime/src/lifetime/object-lifetime.ts diff --git a/packages/universal/timeline/src/timeline/api.ts b/packages/universal/runtime/src/timeline/api.ts similarity index 100% rename from packages/universal/timeline/src/timeline/api.ts rename to packages/universal/runtime/src/timeline/api.ts diff --git a/packages/universal/timeline/src/timeline/frame.ts b/packages/universal/runtime/src/timeline/frame.ts similarity index 100% rename from packages/universal/timeline/src/timeline/frame.ts rename to packages/universal/runtime/src/timeline/frame.ts diff --git a/packages/universal/timeline/src/timeline/frames.ts b/packages/universal/runtime/src/timeline/frames.ts similarity index 97% rename from packages/universal/timeline/src/timeline/frames.ts rename to packages/universal/runtime/src/timeline/frames.ts index 21a44458..8df81706 100644 --- a/packages/universal/timeline/src/timeline/frames.ts +++ b/packages/universal/runtime/src/timeline/frames.ts @@ -127,13 +127,13 @@ export class FrameStack { } /** @internal */ - end(frame: ActiveFrame, value: T): Frame { + end(frame: ActiveFrame, value: T): Frame { return this.#end(frame, value); } /** @internal */ updateSubscriptions(frame: Frame): void { - this.#subscriptions.update(frame); + this.#subscriptions.update(getTag(frame)); } #start( diff --git a/packages/universal/timeline/src/timeline/id.ts b/packages/universal/runtime/src/timeline/id.ts similarity index 100% rename from packages/universal/timeline/src/timeline/id.ts rename to packages/universal/runtime/src/timeline/id.ts diff --git a/packages/universal/timeline/src/timeline/subscriptions.md b/packages/universal/runtime/src/timeline/subscriptions.md similarity index 100% rename from packages/universal/timeline/src/timeline/subscriptions.md rename to packages/universal/runtime/src/timeline/subscriptions.md diff --git a/packages/universal/timeline/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts similarity index 89% rename from packages/universal/timeline/src/timeline/subscriptions.ts rename to packages/universal/runtime/src/timeline/subscriptions.ts index 0a5d1ba6..f02f6abc 100644 --- a/packages/universal/timeline/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -1,11 +1,4 @@ -import type { - CellTag, - Diff, - FormulaTag, - Tag, - Tagged, -} from "@starbeam/interfaces"; -import { getTag } from "@starbeam/tags"; +import type { CellTag, Diff, FormulaTag, Tag } from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { diff } from "./utils.js"; @@ -75,8 +68,8 @@ export class Subscriptions { * we may want to fire notifications whenever a `PolledFormula` is recomputed and produces * different dependencies. */ - register(target: Tagged, ready: NotifyReady): Unsubscribe { - const subscriptionTargets = getTag(target).subscriptionTargets(); + register(target: Tag, ready: NotifyReady): Unsubscribe { + const subscriptionTargets = target.subscriptionTargets(); const unsubscribes = [...subscriptionTargets].map((t) => { const entry = this.#formulaMap.register(t); @@ -106,7 +99,7 @@ export class Subscriptions { * results in removing mappings from cells that are no longer dependencies and adding mappings for * cells that have become dependencies. */ - update(frame: Tagged): void { + update(frame: FormulaTag): void { const cellMap = this.#cellMap; const { add, remove, entry } = this.#formulaMap.update(frame); @@ -125,18 +118,16 @@ class SubscriberMap { readonly #mapping = new WeakMap(); - update( - frame: Tagged - ): Diff & { entry: ReactiveSubscription } { - const entry = this.#mapping.get(getTag(frame)); + update(formula: FormulaTag): Diff & { entry: ReactiveSubscription } { + const entry = this.#mapping.get(formula); if (entry) { - return { ...entry.update(frame), entry }; + return { ...entry.update(formula), entry }; } else { - const entry = ReactiveSubscription.create(getTag(frame)); - this.#mapping.set(getTag(frame), entry); + const entry = ReactiveSubscription.create(formula); + this.#mapping.set(formula, entry); return { - add: new Set(getTag(frame).dependencies()), + add: new Set(formula.dependencies()), remove: new Set(), entry, }; @@ -179,9 +170,9 @@ class ReactiveSubscription { } } - update(frame: Tagged): Diff { + update(frame: FormulaTag): Diff { const prev = this.#deps; - const next = new Set(getTag(frame).dependencies()); + const next = new Set(frame.dependencies()); this.#deps = next; return diff(prev, next); diff --git a/packages/universal/timeline/src/timeline/timeline.ts b/packages/universal/runtime/src/timeline/timeline.ts similarity index 97% rename from packages/universal/timeline/src/timeline/timeline.ts rename to packages/universal/runtime/src/timeline/timeline.ts index af8eb254..29a13c95 100644 --- a/packages/universal/timeline/src/timeline/timeline.ts +++ b/packages/universal/runtime/src/timeline/timeline.ts @@ -42,7 +42,7 @@ export class Timeline { on = { change: (target: Tagged, ready: NotifyReady): Unsubscribe => { - return this.#subscriptions.register(target, ready); + return this.#subscriptions.register(getTag(target), ready); }, } as const; @@ -161,7 +161,7 @@ export class Timeline { * possible change to their dependencies. */ update(reactive: interfaces.Tagged): void { - this.#subscriptions.update(reactive); + this.#subscriptions.update(getTag(reactive)); } willEvaluate(): void { diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts new file mode 100644 index 00000000..c90b6fdc --- /dev/null +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -0,0 +1,58 @@ +import type { CellTag, Tag, Tagged, Unsubscribe } from "@starbeam/interfaces"; +import { getTag, type Timestamp } from "@starbeam/tags"; +import { type FormulaTag, NOW } from "@starbeam/tags"; + +import { type NotifyReady, Subscriptions } from "./subscriptions.js"; + +enum Phase { + read = "read", + write = "write", +} + +/** + * The Timeline is the core of the runtime. + * + * Subscribers use the Timeline to subscribe to notifications for specific + * `Tagged` values. Reactive implementations that use `FormulaTag` are + * responsible for notifying the timeline when their dependencies change. + */ +class Mutations { + readonly #subscriptions = Subscriptions.create(); + readonly #lastPhase: Phase = Phase.read; + + subscribe(target: Tag, ready: NotifyReady): Unsubscribe { + return this.#subscriptions.register(target, ready); + } + + bump(cell: CellTag): Timestamp { + const next = this.#updatePhase(Phase.write); + this.#subscriptions.notify(cell); + return next; + } + + update(formula: FormulaTag): void { + this.#subscriptions.update(formula); + } + + #updatePhase(phase: Phase): Timestamp { + if (this.#lastPhase === phase) { + return NOW.now; + } else { + return NOW.bump(); + } + } +} + +export const MUTATIONS = new Mutations(); + +export class PublicTimeline { + readonly on = { + change: (target: Tagged, ready: NotifyReady): Unsubscribe => { + return MUTATIONS.subscribe(getTag(target), ready); + }, + }; + + get now(): Timestamp { + return NOW.now; + } +} diff --git a/packages/universal/timeline/src/timeline/utils.ts b/packages/universal/runtime/src/timeline/utils.ts similarity index 100% rename from packages/universal/timeline/src/timeline/utils.ts rename to packages/universal/runtime/src/timeline/utils.ts diff --git a/packages/universal/runtime/src/tracking-stack.ts b/packages/universal/runtime/src/tracking-stack.ts new file mode 100644 index 00000000..da9b1d98 --- /dev/null +++ b/packages/universal/runtime/src/tracking-stack.ts @@ -0,0 +1,46 @@ +import { iterableHasItems } from "@starbeam/core-utils"; +import type { Tag } from "@starbeam/interfaces"; + +export class TrackingStack { + static create(): TrackingStack { + return new TrackingStack(); + } + + #current: TrackingFrameData | undefined; + + start({ + intoTag, + }: { + intoTag: (tags: Set) => T; + }): () => T { + const frame: TrackingFrameData = { consumed: new Set() }; + const parent = this.#current; + this.#current = frame; + + return () => { + const tag = intoTag(frame.consumed); + + if (parent) { + this.#current = parent; + + if (iterableHasItems(tag.dependencies())) { + parent.consumed.add(tag); + } + } + + return tag; + }; + } + + consume(tag: Tag): void { + const current = this.#current; + + if (current) { + current.consumed.add(tag); + } + } +} + +export interface TrackingFrameData { + readonly consumed: Set; +} diff --git a/packages/universal/timeline/tests/.eslintrc.json b/packages/universal/runtime/tests/.eslintrc.json similarity index 69% rename from packages/universal/timeline/tests/.eslintrc.json rename to packages/universal/runtime/tests/.eslintrc.json index d73a5ae3..8264737d 100644 --- a/packages/universal/timeline/tests/.eslintrc.json +++ b/packages/universal/runtime/tests/.eslintrc.json @@ -5,7 +5,7 @@ "extends": ["plugin:@starbeam/loose"], "files": ["**/*.ts"], "parserOptions": { - "project": "packages/universal/timeline/tests/tsconfig.json" + "project": "packages/universal/runtime/tests/tsconfig.json" } } ] diff --git a/packages/universal/timeline/tests/.npmrc b/packages/universal/runtime/tests/.npmrc similarity index 100% rename from packages/universal/timeline/tests/.npmrc rename to packages/universal/runtime/tests/.npmrc diff --git a/packages/universal/timeline/tests/CHANGELOG.md b/packages/universal/runtime/tests/CHANGELOG.md similarity index 100% rename from packages/universal/timeline/tests/CHANGELOG.md rename to packages/universal/runtime/tests/CHANGELOG.md diff --git a/packages/universal/timeline/tests/consume.spec.ts b/packages/universal/runtime/tests/consume.spec.ts similarity index 97% rename from packages/universal/timeline/tests/consume.spec.ts rename to packages/universal/runtime/tests/consume.spec.ts index 743125dc..0db76ef1 100644 --- a/packages/universal/timeline/tests/consume.spec.ts +++ b/packages/universal/runtime/tests/consume.spec.ts @@ -1,6 +1,6 @@ import { descriptionFrom, Stack } from "@starbeam/debug"; import { getID } from "@starbeam/shared"; -import { TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; import { Cell, Formula, Marker } from "./support/mini-reactives.js"; diff --git a/packages/universal/timeline/tests/lifetime.spec.ts b/packages/universal/runtime/tests/lifetime.spec.ts similarity index 99% rename from packages/universal/timeline/tests/lifetime.spec.ts rename to packages/universal/runtime/tests/lifetime.spec.ts index 12e25969..5d475015 100644 --- a/packages/universal/timeline/tests/lifetime.spec.ts +++ b/packages/universal/runtime/tests/lifetime.spec.ts @@ -1,4 +1,4 @@ -import { LIFETIME } from "@starbeam/timeline"; +import { LIFETIME } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; describe("lifetimes", () => { diff --git a/packages/universal/timeline/tests/package.json b/packages/universal/runtime/tests/package.json similarity index 89% rename from packages/universal/timeline/tests/package.json rename to packages/universal/runtime/tests/package.json index 119343b6..09111099 100644 --- a/packages/universal/timeline/tests/package.json +++ b/packages/universal/runtime/tests/package.json @@ -12,6 +12,6 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", - "@starbeam/timeline": "workspace:^" + "@starbeam/runtime": "workspace:^" } } diff --git a/packages/universal/timeline/tests/pollable.spec.ts b/packages/universal/runtime/tests/pollable.spec.ts similarity index 98% rename from packages/universal/timeline/tests/pollable.spec.ts rename to packages/universal/runtime/tests/pollable.spec.ts index 20686e7c..0f855724 100644 --- a/packages/universal/timeline/tests/pollable.spec.ts +++ b/packages/universal/runtime/tests/pollable.spec.ts @@ -2,7 +2,7 @@ import { isPresentArray } from "@starbeam/core-utils"; import { Desc, descriptionFrom } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; import { DelegateTag } from "@starbeam/tags"; -import { Frame, TAG, TIMELINE } from "@starbeam/timeline"; +import { Frame, TAG, TIMELINE } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; import { Cell } from "./support/mini-reactives.js"; diff --git a/packages/universal/timeline/tests/protocol.spec.ts b/packages/universal/runtime/tests/protocol.spec.ts similarity index 98% rename from packages/universal/timeline/tests/protocol.spec.ts rename to packages/universal/runtime/tests/protocol.spec.ts index 8a16be51..3e4eb214 100644 --- a/packages/universal/timeline/tests/protocol.spec.ts +++ b/packages/universal/runtime/tests/protocol.spec.ts @@ -8,7 +8,7 @@ import { lastUpdatedInTaggedList, zero, } from "@starbeam/tags"; -import { TAG, TIMELINE } from "@starbeam/timeline"; +import { TAG, TIMELINE } from "@starbeam/runtime"; import { beforeAll, describe, expect, it } from "vitest"; import { Cell, FreezableCell, Static } from "./support/mini-reactives.js"; diff --git a/packages/universal/timeline/tests/subscription.ts b/packages/universal/runtime/tests/subscription.ts similarity index 97% rename from packages/universal/timeline/tests/subscription.ts rename to packages/universal/runtime/tests/subscription.ts index 0e7f00d1..116abacd 100644 --- a/packages/universal/timeline/tests/subscription.ts +++ b/packages/universal/runtime/tests/subscription.ts @@ -1,5 +1,5 @@ import { Desc } from "@starbeam/debug"; -import { Frame, TIMELINE } from "@starbeam/timeline"; +import { Frame, TIMELINE } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; import { Cell } from "./support/mini-reactives.js"; diff --git a/packages/universal/timeline/tests/support/mini-reactives.ts b/packages/universal/runtime/tests/support/mini-reactives.ts similarity index 97% rename from packages/universal/timeline/tests/support/mini-reactives.ts rename to packages/universal/runtime/tests/support/mini-reactives.ts index 15c0450a..2bb5d30d 100644 --- a/packages/universal/timeline/tests/support/mini-reactives.ts +++ b/packages/universal/runtime/tests/support/mini-reactives.ts @@ -7,7 +7,7 @@ import { import type { ReactiveCell, ReactiveValue, Tagged } from "@starbeam/interfaces"; import { TAG, type UNINITIALIZED } from "@starbeam/shared"; import { CellTag, StaticTag } from "@starbeam/tags"; -import { diff, Frame, TIMELINE } from "@starbeam/timeline"; +import { diff, Frame, TIMELINE } from "@starbeam/runtime"; export interface FreezableCell extends ReactiveCell { freeze: () => void; diff --git a/packages/universal/timeline/tests/support/testing.ts b/packages/universal/runtime/tests/support/testing.ts similarity index 100% rename from packages/universal/timeline/tests/support/testing.ts rename to packages/universal/runtime/tests/support/testing.ts diff --git a/packages/universal/timeline/tests/tsconfig.json b/packages/universal/runtime/tests/tsconfig.json similarity index 100% rename from packages/universal/timeline/tests/tsconfig.json rename to packages/universal/runtime/tests/tsconfig.json diff --git a/packages/universal/timeline/tsconfig.json b/packages/universal/runtime/tsconfig.json similarity index 100% rename from packages/universal/timeline/tsconfig.json rename to packages/universal/runtime/tsconfig.json diff --git a/packages/universal/test-utils/package.json b/packages/universal/test-utils/package.json index da12dc18..9ec3d4de 100644 --- a/packages/universal/test-utils/package.json +++ b/packages/universal/test-utils/package.json @@ -24,7 +24,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index c3f5eb39..3b7f2fa1 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -54,4 +54,4 @@ export { type VariantType, } from "./src/reactive-core/variants.js"; export { Cell, type Equality, Static } from "@starbeam/reactive"; -export { LIFETIME, TAG, TIMELINE } from "@starbeam/timeline"; +export { LIFETIME, TAG, TIMELINE } from "@starbeam/runtime"; diff --git a/packages/universal/universal/package.json b/packages/universal/universal/package.json index a8ea92d1..784cf614 100644 --- a/packages/universal/universal/package.json +++ b/packages/universal/universal/package.json @@ -31,7 +31,7 @@ "@starbeam/reactive": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/verify": "workspace:^" }, "devDependencies": { diff --git a/packages/universal/universal/src/debug-renderer.ts b/packages/universal/universal/src/debug-renderer.ts index 8d74ae66..4aa48395 100644 --- a/packages/universal/universal/src/debug-renderer.ts +++ b/packages/universal/universal/src/debug-renderer.ts @@ -1,6 +1,6 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; -import type { Unsubscribe } from "@starbeam/timeline"; -import { TIMELINE } from "@starbeam/timeline"; +import type { Unsubscribe } from "@starbeam/runtime"; +import { TIMELINE } from "@starbeam/runtime"; import { Formula } from "./reactive-core/formula/formula.js"; diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/universal/src/reactive-core/delegate.ts index f3feff45..1e34358f 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/universal/src/reactive-core/delegate.ts @@ -1,7 +1,7 @@ import { callerStack, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; import { DelegateTag, taggedDescription } from "@starbeam/tags"; -import { TAG } from "@starbeam/timeline"; +import { TAG } from "../../../runtime"; export function Wrap( reactive: U, diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts index 07f6b796..44c3297d 100644 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/formula.ts @@ -4,9 +4,9 @@ import { descriptionFrom, } from "@starbeam/debug"; import type { Reactive, Stack } from "@starbeam/interfaces"; +import { diff, Frame, TAG, TIMELINE } from "@starbeam/runtime"; import type { UNINITIALIZED } from "@starbeam/shared"; import { DelegateTag, getTag } from "@starbeam/tags"; -import { diff, Frame, TAG, TIMELINE } from "@starbeam/timeline"; export interface FormulaValidation { frame: Frame; diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts index fb2e2ba7..c296439d 100644 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts @@ -5,9 +5,9 @@ import { descriptionFrom, } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; +import { diff, Frame, TAG, TIMELINE } from "@starbeam/runtime"; import type { UNINITIALIZED } from "@starbeam/shared"; import { DelegateTag, getTag } from "@starbeam/tags"; -import { diff, Frame, TAG, TIMELINE } from "@starbeam/timeline"; import type { Formula } from "./formula.js"; diff --git a/packages/universal/universal/src/reactive-core/formula/setups.ts b/packages/universal/universal/src/reactive-core/formula/setups.ts index 98761ac0..e4fde52d 100644 --- a/packages/universal/universal/src/reactive-core/formula/setups.ts +++ b/packages/universal/universal/src/reactive-core/formula/setups.ts @@ -1,6 +1,6 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; +import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; import { getID } from "@starbeam/shared"; -import { type Unsubscribe, LIFETIME } from "@starbeam/timeline"; import { Marker } from "../marker.js"; import { Formula } from "./formula.js"; diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts index d60f01f9..fee101cb 100644 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ b/packages/universal/universal/src/reactive-core/marker.ts @@ -1,8 +1,8 @@ import { callerStack, Desc, type Description } from "@starbeam/debug"; import type { Stack, Tagged } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; +import { TAG, TIMELINE } from "@starbeam/runtime"; import { CellTag } from "@starbeam/tags"; -import { TAG, TIMELINE } from "@starbeam/timeline"; import { RUNTIME } from "../runtime.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/resource.ts b/packages/universal/universal/src/reactive-core/resource/resource.ts index 5873732d..76380ab4 100644 --- a/packages/universal/universal/src/reactive-core/resource/resource.ts +++ b/packages/universal/universal/src/reactive-core/resource/resource.ts @@ -16,8 +16,8 @@ import { Desc, type Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; import { Static } from "@starbeam/reactive"; +import { LIFETIME } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; -import { LIFETIME } from "@starbeam/timeline"; import { isWeakKey } from "@starbeam/verify"; import { Formula } from "../formula/formula.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/run.ts b/packages/universal/universal/src/reactive-core/resource/run.ts index 765a02ef..9f6ddbbe 100644 --- a/packages/universal/universal/src/reactive-core/resource/run.ts +++ b/packages/universal/universal/src/reactive-core/resource/run.ts @@ -1,6 +1,6 @@ import { Desc, type Description } from "@starbeam/debug"; import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { LIFETIME, type Unsubscribe } from "@starbeam/timeline"; +import { LIFETIME, type Unsubscribe } from "../../../../runtime"; import type { Handler, Resource, ResourceBlueprint } from "./resource"; import type { ResourceState } from "./state.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts index fcc0dcc4..af21efdb 100644 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ b/packages/universal/universal/src/reactive-core/resource/state.ts @@ -1,8 +1,8 @@ import type { Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; import { isReactive, Static } from "@starbeam/reactive"; +import { LIFETIME } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; -import { LIFETIME } from "@starbeam/timeline"; import { Formula } from "../formula/formula.js"; import { diff --git a/packages/universal/universal/src/reactive-core/service.ts b/packages/universal/universal/src/reactive-core/service.ts index 4072842b..7d7535b5 100644 --- a/packages/universal/universal/src/reactive-core/service.ts +++ b/packages/universal/universal/src/reactive-core/service.ts @@ -1,6 +1,6 @@ import { Desc } from "@starbeam/debug"; import type { Description, Reactive } from "@starbeam/interfaces"; -import { CONTEXT } from "@starbeam/timeline"; +import { CONTEXT } from "@starbeam/runtime"; import { Factory, type IntoResource } from "./into.js"; import type { Blueprint } from "./reactive.js"; diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index 085a751c..ff8cd9af 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -6,11 +6,11 @@ import { DisplayStruct, } from "@starbeam/debug"; import { Cell } from "@starbeam/reactive"; +import type { Tagged } from "@starbeam/runtime"; +import { TAG, TIMELINE } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; import { FormulaTag } from "@starbeam/tags"; import { DelegateTag } from "@starbeam/tags"; -import type { Tagged } from "@starbeam/timeline"; -import { TAG, TIMELINE } from "@starbeam/timeline"; import { Marker } from "./marker.js"; diff --git a/packages/universal/universal/src/runtime.ts b/packages/universal/universal/src/runtime.ts index 57ea5a43..b9e58200 100644 --- a/packages/universal/universal/src/runtime.ts +++ b/packages/universal/universal/src/runtime.ts @@ -7,7 +7,7 @@ import type { Timestamp, } from "@starbeam/interfaces"; import { defineRuntime } from "@starbeam/reactive"; -import { TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "../../runtime"; type Timeline = typeof TIMELINE; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index 6072e59d..b6f22c4a 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,7 +1,7 @@ import { entryPointFn } from "@starbeam/debug"; import { Static } from "@starbeam/reactive"; import { describeTagged } from "@starbeam/tags"; -import { Frame } from "@starbeam/timeline"; +import { Frame } from "../../runtime"; import { Cell, FormulaValidation, Reactive } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; diff --git a/packages/universal/universal/tests/package.json b/packages/universal/universal/tests/package.json index d14436d1..fd2cd854 100644 --- a/packages/universal/universal/tests/package.json +++ b/packages/universal/universal/tests/package.json @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/js": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" }, "devDependencies": { diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts index 62fc5c31..5b173ed4 100644 --- a/packages/universal/universal/tests/setup.spec.ts +++ b/packages/universal/universal/tests/setup.spec.ts @@ -1,5 +1,5 @@ import { getTag } from "@starbeam/tags"; -import { TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "../../runtime"; import { Cell, Setup } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 5e10c466..6dfbae4f 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,5 +1,5 @@ import { describeTagged } from "@starbeam/tags"; -import { type Tagged } from "@starbeam/timeline"; +import { type Tagged } from "../../runtime"; import { Formula, TIMELINE, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/x/devtool/package.json b/packages/x/devtool/package.json index 0748d80a..0e70ecb6 100644 --- a/packages/x/devtool/package.json +++ b/packages/x/devtool/package.json @@ -33,7 +33,7 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/tags": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/verify": "workspace:^", "preact": "^10.13.1" }, diff --git a/packages/x/devtool/src/log/frame.tsx b/packages/x/devtool/src/log/frame.tsx index 2ab44dc1..986e10a4 100644 --- a/packages/x/devtool/src/log/frame.tsx +++ b/packages/x/devtool/src/log/frame.tsx @@ -2,7 +2,7 @@ import type { FrameConsumeOperation } from "@starbeam/debug"; import type { MutableInternals, Timestamp } from "@starbeam/interfaces"; -import { ReactiveInternals } from "@starbeam/timeline"; +import { ReactiveInternals } from "@starbeam/runtime"; import type { JSX } from "preact"; import { DescribeLeaf } from "./describe.js"; diff --git a/packages/x/devtool/src/log/log.tsx b/packages/x/devtool/src/log/log.tsx index c5091128..03926f2b 100644 --- a/packages/x/devtool/src/log/log.tsx +++ b/packages/x/devtool/src/log/log.tsx @@ -3,7 +3,7 @@ import "preact"; /** @jsxRuntime automatic @jsxImportSource preact */ import type { DebugOperation } from "@starbeam/debug"; import type { Timestamp } from "@starbeam/interfaces"; -import { TIMELINE } from "@starbeam/timeline"; +import { TIMELINE } from "@starbeam/runtime"; import type { JSX } from "preact"; import { useMemo, useState } from "preact/hooks"; diff --git a/packages/x/devtool/src/log/ui.tsx b/packages/x/devtool/src/log/ui.tsx index 646fe4e5..fd7b3434 100644 --- a/packages/x/devtool/src/log/ui.tsx +++ b/packages/x/devtool/src/log/ui.tsx @@ -1,7 +1,7 @@ /** @jsxRuntime automatic @jsxImportSource preact */ import type { DescriptionParts } from "@starbeam/debug"; -import { Timestamp } from "@starbeam/timeline"; +import { Timestamp } from "@starbeam/runtime"; import type { ComponentChildren, JSX } from "preact"; import { useState } from "preact/hooks"; diff --git a/packages/x/devtool/src/single/single-reactive.tsx b/packages/x/devtool/src/single/single-reactive.tsx index cb4b6e3d..38cb6c36 100644 --- a/packages/x/devtool/src/single/single-reactive.tsx +++ b/packages/x/devtool/src/single/single-reactive.tsx @@ -8,7 +8,7 @@ import type { import type { CellTag } from "@starbeam/interfaces"; import { getTag } from "@starbeam/tags"; import { taggedDescription } from "@starbeam/tags"; -import { type Tagged, TIMELINE } from "@starbeam/timeline"; +import { type Tagged, TIMELINE } from "@starbeam/runtime"; import { isPresent, verified } from "@starbeam/verify"; import { type JSX, render } from "preact"; diff --git a/packages/x/vanilla/package.json b/packages/x/vanilla/package.json index ce4de29c..9fd1cd67 100644 --- a/packages/x/vanilla/package.json +++ b/packages/x/vanilla/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "@starbeam/debug": "workspace:^", - "@starbeam/timeline": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" }, "devDependencies": { diff --git a/packages/x/vanilla/src/dom.ts b/packages/x/vanilla/src/dom.ts index 9f2efd6e..73e6eedd 100644 --- a/packages/x/vanilla/src/dom.ts +++ b/packages/x/vanilla/src/dom.ts @@ -1,6 +1,6 @@ import type { Description } from "@starbeam/debug"; import { descriptionFrom } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/timeline"; +import type { Reactive } from "@starbeam/runtime"; import { Formula, LIFETIME } from "@starbeam/universal"; import { Cursor } from "./cursor.js"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be9f0c69..7419d5fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -162,7 +162,7 @@ importers: '@esbuild-plugins/node-globals-polyfill': ^0.1.1 '@starbeam/js': workspace:^ '@starbeam/preact': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ '@vitest/ui': '*' preact: ^10.11.3 @@ -173,7 +173,7 @@ importers: dependencies: '@starbeam/js': link:../../packages/universal/js '@starbeam/preact': link:../../packages/preact/preact - '@starbeam/timeline': link:../../packages/universal/timeline + '@starbeam/runtime': link:../../packages/universal/runtime '@starbeam/universal': link:../../packages/universal/universal preact: 10.11.3 purecss: 3.0.0 @@ -408,7 +408,7 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/preact-utils': workspace:^ '@starbeam/reactive': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ chalk: ^5.2.0 @@ -419,7 +419,7 @@ importers: '@starbeam/debug': link:../../universal/debug '@starbeam/preact-utils': link:../preact-utils '@starbeam/reactive': link:../../universal/reactive - '@starbeam/timeline': link:../../universal/timeline + '@starbeam/runtime': link:../../universal/runtime '@starbeam/universal': link:../../universal/universal '@starbeam/verify': link:../../universal/verify preact: 10.11.3 @@ -453,7 +453,7 @@ importers: '@starbeam-workspace/test-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/preact': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ '@testing-library/dom': ^8.19.1 '@testing-library/preact': ^3.2.2 @@ -466,7 +466,7 @@ importers: '@starbeam-workspace/test-utils': link:../../../universal/test-utils '@starbeam/debug': link:../../../universal/debug '@starbeam/preact': link:../../preact - '@starbeam/timeline': link:../../../universal/timeline + '@starbeam/runtime': link:../../../universal/runtime '@starbeam/universal': link:../../../universal/universal '@testing-library/dom': 8.19.1 '@testing-library/preact': 3.2.2_preact@10.11.3 @@ -492,7 +492,7 @@ importers: '@starbeam-workspace/test-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/preact': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ '@testing-library/dom': ^8.19.1 '@testing-library/preact': ^3.2.2 @@ -504,7 +504,7 @@ importers: '@starbeam-workspace/test-utils': link:../../../universal/test-utils '@starbeam/debug': link:../../../universal/debug '@starbeam/preact': link:../../preact - '@starbeam/timeline': link:../../../universal/timeline + '@starbeam/runtime': link:../../../universal/runtime '@starbeam/universal': link:../../../universal/universal '@testing-library/dom': 8.19.1 '@testing-library/preact': 3.2.2_preact@10.11.3 @@ -520,7 +520,7 @@ importers: '@starbeam-workspace/test-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/preact': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ '@testing-library/dom': ^8.19.1 '@testing-library/preact': ^3.2.2 @@ -532,7 +532,7 @@ importers: '@starbeam-workspace/test-utils': link:../../../universal/test-utils '@starbeam/debug': link:../../../universal/debug '@starbeam/preact': link:.. - '@starbeam/timeline': link:../../../universal/timeline + '@starbeam/runtime': link:../../../universal/runtime '@starbeam/universal': link:../../../universal/universal '@testing-library/dom': 8.19.1 '@testing-library/preact': 3.2.2_preact@10.11.3 @@ -551,8 +551,8 @@ importers: '@starbeam/js': workspace:^ '@starbeam/modifier': workspace:^ '@starbeam/reactive': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/shared': workspace:^ - '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/use-strict-lifecycle': workspace:^ '@starbeam/verify': workspace:^ @@ -567,8 +567,8 @@ importers: '@starbeam/js': link:../../universal/js '@starbeam/modifier': link:../../universal/modifier '@starbeam/reactive': link:../../universal/reactive + '@starbeam/runtime': link:../../universal/runtime '@starbeam/shared': link:../../universal/shared - '@starbeam/timeline': link:../../universal/timeline '@starbeam/universal': link:../../universal/universal '@starbeam/use-strict-lifecycle': link:../use-strict-lifecycle '@starbeam/verify': link:../../universal/verify @@ -587,7 +587,7 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/react': workspace:^ '@starbeam/reactive': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ jsdom: ^21.1.1 react: ^18.2.0 @@ -598,7 +598,7 @@ importers: '@starbeam/debug': link:../../../universal/debug '@starbeam/react': link:.. '@starbeam/reactive': link:../../../universal/reactive - '@starbeam/timeline': link:../../../universal/timeline + '@starbeam/runtime': link:../../../universal/runtime '@starbeam/universal': link:../../../universal/universal jsdom: 21.1.1 react: 18.2.0 @@ -726,17 +726,17 @@ importers: '@starbeam-dev/build-support': workspace:* '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/tags': workspace:^ - '@starbeam/timeline': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ dependencies: '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces + '@starbeam/runtime': link:../runtime '@starbeam/shared': link:../shared '@starbeam/tags': link:../tags - '@starbeam/timeline': link:../timeline '@starbeam/universal': link:../universal '@starbeam/verify': link:../verify devDependencies: @@ -788,6 +788,37 @@ importers: devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build + packages/universal/runtime: + specifiers: + '@starbeam-dev/build-support': workspace:* + '@starbeam/core-utils': workspace:^ + '@starbeam/debug': workspace:^ + '@starbeam/interfaces': workspace:^ + '@starbeam/shared': workspace:^ + '@starbeam/tags': workspace:^ + '@starbeam/verify': workspace:^ + dependencies: + '@starbeam/core-utils': link:../core-utils + '@starbeam/debug': link:../debug + '@starbeam/interfaces': link:../interfaces + '@starbeam/shared': link:../shared + '@starbeam/tags': link:../tags + '@starbeam/verify': link:../verify + devDependencies: + '@starbeam-dev/build-support': link:../../../workspace/build + + packages/universal/runtime/tests: + specifiers: + '@starbeam/debug': workspace:^ + '@starbeam/interfaces': workspace:^ + '@starbeam/runtime': workspace:^ + '@starbeam/shared': workspace:^ + dependencies: + '@starbeam/debug': link:../../debug + '@starbeam/interfaces': link:../../interfaces + '@starbeam/runtime': link:.. + '@starbeam/shared': link:../../shared + packages/universal/shared: specifiers: '@starbeam-dev/build-support': workspace:* @@ -816,47 +847,16 @@ importers: packages/universal/test-utils: specifiers: '@starbeam-dev/build-support': workspace:* - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ dependencies: - '@starbeam/timeline': link:../timeline + '@starbeam/runtime': link:../runtime '@starbeam/universal': link:../universal '@starbeam/verify': link:../verify devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build - packages/universal/timeline: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/verify': workspace:^ - dependencies: - '@starbeam/core-utils': link:../core-utils - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/shared': link:../shared - '@starbeam/tags': link:../tags - '@starbeam/verify': link:../verify - devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build - - packages/universal/timeline/tests: - specifiers: - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/timeline': workspace:^ - dependencies: - '@starbeam/debug': link:../../debug - '@starbeam/interfaces': link:../../interfaces - '@starbeam/shared': link:../../shared - '@starbeam/timeline': link:.. - packages/universal/universal: specifiers: '@starbeam-dev/build-support': workspace:* @@ -864,18 +864,18 @@ importers: '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ '@starbeam/reactive': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/tags': workspace:^ - '@starbeam/timeline': workspace:^ '@starbeam/verify': workspace:^ dependencies: '@starbeam/core-utils': link:../core-utils '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces '@starbeam/reactive': link:../reactive + '@starbeam/runtime': link:../runtime '@starbeam/shared': link:../shared '@starbeam/tags': link:../tags - '@starbeam/timeline': link:../timeline '@starbeam/verify': link:../verify devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build @@ -885,12 +885,12 @@ importers: '@starbeam-workspace/test-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/js': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ dependencies: '@starbeam/debug': link:../../debug '@starbeam/js': link:../../js - '@starbeam/timeline': link:../../timeline + '@starbeam/runtime': link:../../runtime '@starbeam/universal': link:.. devDependencies: '@starbeam-workspace/test-utils': link:../../test-utils @@ -916,16 +916,16 @@ importers: '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/tags': workspace:^ - '@starbeam/timeline': workspace:^ '@starbeam/verify': workspace:^ preact: ^10.11.3 dependencies: '@starbeam/core-utils': link:../../universal/core-utils '@starbeam/debug': link:../../universal/debug '@starbeam/interfaces': link:../../universal/interfaces + '@starbeam/runtime': link:../../universal/runtime '@starbeam/tags': link:../../universal/tags - '@starbeam/timeline': link:../../universal/timeline '@starbeam/verify': link:../../universal/verify preact: 10.11.3 devDependencies: @@ -974,11 +974,11 @@ importers: specifiers: '@starbeam-dev/build-support': workspace:* '@starbeam/debug': workspace:^ - '@starbeam/timeline': workspace:^ + '@starbeam/runtime': workspace:^ '@starbeam/universal': workspace:^ dependencies: '@starbeam/debug': link:../../universal/debug - '@starbeam/timeline': link:../../universal/timeline + '@starbeam/runtime': link:../../universal/runtime '@starbeam/universal': link:../../universal/universal devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build diff --git a/workspace/@domtree/any/package.json b/workspace/@domtree/any/package.json index 16ada182..483a669d 100644 --- a/workspace/@domtree/any/package.json +++ b/workspace/@domtree/any/package.json @@ -2,7 +2,11 @@ "name": "@domtree/any", "version": "0.9.3", "type": "module", + "main": "index.ts", "types": "index.ts", + "exports": { + "default": "./index.ts" + }, "publishConfig": { "exports": { ".": { diff --git a/workspace/@domtree/browser/package.json b/workspace/@domtree/browser/package.json index 0bf84422..b179aa9f 100644 --- a/workspace/@domtree/browser/package.json +++ b/workspace/@domtree/browser/package.json @@ -2,7 +2,11 @@ "name": "@domtree/browser", "version": "0.9.3", "type": "module", + "main": "index.ts", "types": "index.ts", + "exports": { + "default": "./index.ts" + }, "publishConfig": { "exports": { ".": { diff --git a/workspace/@domtree/flavors/package.json b/workspace/@domtree/flavors/package.json index 6608cf36..c39988a6 100644 --- a/workspace/@domtree/flavors/package.json +++ b/workspace/@domtree/flavors/package.json @@ -2,7 +2,11 @@ "name": "@domtree/flavors", "version": "0.9.3", "type": "module", + "main": "index.ts", "types": "index.ts", + "exports": { + "default": "./index.ts" + }, "publishConfig": { "exports": { ".": { diff --git a/workspace/@domtree/interface/package.json b/workspace/@domtree/interface/package.json index f19e3398..0a7c4f6a 100644 --- a/workspace/@domtree/interface/package.json +++ b/workspace/@domtree/interface/package.json @@ -2,7 +2,11 @@ "name": "@domtree/interface", "version": "0.9.3", "type": "module", + "main": "index.ts", "types": "index.ts", + "exports": { + "default": "./index.ts" + }, "publishConfig": { "exports": { ".": { diff --git a/workspace/@domtree/minimal/package.json b/workspace/@domtree/minimal/package.json index f8365a2b..74e020d2 100644 --- a/workspace/@domtree/minimal/package.json +++ b/workspace/@domtree/minimal/package.json @@ -2,7 +2,11 @@ "name": "@domtree/minimal", "version": "0.9.3", "type": "module", + "main": "index.ts", "types": "index.ts", + "exports": { + "default": "./index.ts" + }, "publishConfig": { "exports": { ".": { From 63f49e02530f219501b510e8a8daa5a33d625642 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sat, 25 Mar 2023 19:13:07 -0700 Subject: [PATCH 10/46] Fix tests --- packages/universal/interfaces/index.d.ts | 2 +- .../universal/interfaces/src/protocol.d.ts | 6 +- .../universal/interfaces/src/runtime.d.ts | 16 ++- packages/universal/reactive/index.ts | 2 + packages/universal/reactive/package.json | 1 + .../reactive/src/primitives/formula.ts | 101 ++++++++++++++---- .../reactive/src/primitives/marker.ts | 2 +- packages/universal/reactive/src/runtime.ts | 2 +- .../universal/reactive/tests/.eslintrc.json | 12 +++ packages/universal/reactive/tests/.npmrc | 2 + .../universal/reactive/tests/package.json | 17 +++ packages/universal/runtime/index.ts | 6 ++ .../universal/runtime/src/timeline/frame.ts | 25 +++-- .../universal/runtime/src/timeline/frames.ts | 2 +- .../universal/runtime/src/timeline/tracker.ts | 2 + .../universal/runtime/src/tracking-stack.ts | 2 + packages/universal/runtime/tests/package.json | 6 +- packages/universal/tags/src/tag.ts | 23 ++-- packages/universal/universal/package.json | 2 +- .../reactive-core/formula/tracked-formula.ts | 0 20 files changed, 173 insertions(+), 58 deletions(-) create mode 100644 packages/universal/reactive/tests/.eslintrc.json create mode 100644 packages/universal/reactive/tests/.npmrc create mode 100644 packages/universal/reactive/tests/package.json create mode 100644 packages/universal/universal/src/reactive-core/formula/tracked-formula.ts diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 78783c27..cab01ea7 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -38,7 +38,6 @@ export type { ReactiveFormula, ReactiveId, ReactiveValue, - Runtime, SpecificTag, StaticTag, Tag, @@ -47,6 +46,7 @@ export type { TagType, UpdateOptions, } from "./src/protocol.js"; +export type { Runtime } from "./src/runtime.js"; export type { DisplayParts, Stack, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 18951633..06166865 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -11,7 +11,7 @@ export interface AbstractTag { readonly description: Description; } -export type List = Iterable; +export type List = Iterable | T[] | readonly T[]; export class TagMethods { readonly id: ReactiveId; @@ -58,7 +58,7 @@ export interface CellTag extends AbstractTag, TagMethods { */ export interface FormulaTag extends AbstractTag, TagMethods { readonly type: "formula"; - children: () => readonly Tagged[]; + children: () => readonly Tag[]; } /** @@ -72,7 +72,7 @@ export interface FormulaTag extends AbstractTag, TagMethods { */ export interface DelegateTag extends AbstractTag, TagMethods { readonly type: "delegate"; - readonly targets: readonly Tagged[]; + readonly targets: readonly Tag[]; } /** diff --git a/packages/universal/interfaces/src/runtime.d.ts b/packages/universal/interfaces/src/runtime.d.ts index 6687dd8b..3f8ad053 100644 --- a/packages/universal/interfaces/src/runtime.d.ts +++ b/packages/universal/interfaces/src/runtime.d.ts @@ -1,5 +1,6 @@ +import type { Unsubscribe } from "./aliases.js"; import type { Description } from "./description.js"; -import type { CellTag, Tagged } from "./protocol.js"; +import type { CellTag, Tag, Tagged } from "./protocol.js"; import type { Stack as CallStack } from "./stack.js"; import type { Timestamp } from "./timestamp.js"; @@ -12,6 +13,19 @@ export interface Runtime { description: Description, frame: RuntimeFrame ) => ActiveRuntimeFrame; + readonly subscriptions: SubscriptionRuntime; + readonly autotracking: AutotrackingRuntime; +} + +export interface SubscriptionRuntime { + subscribe: (target: Tag, ready: NotifyReady) => Unsubscribe; + bump: (cell: CellTag) => Timestamp; + update: (formula: FormulaTag) => void; +} + +export interface AutotrackingRuntime { + start: () => () => Set; + consume: (tag: Tag) => void; } export interface ActiveRuntimeFrame { diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 1973dcb2..30a4e458 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -1,5 +1,7 @@ export type { CellOptions, Equality } from "./src/primitives/cell.js"; export { Cell } from "./src/primitives/cell.js"; +export { Formula } from "./src/primitives/formula.js"; +export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; export { defineRuntime, getRuntime } from "./src/runtime.js"; export { intoReactive, isReactive, read } from "./src/utils.js"; diff --git a/packages/universal/reactive/package.json b/packages/universal/reactive/package.json index cb79b50c..dacd6cf8 100644 --- a/packages/universal/reactive/package.json +++ b/packages/universal/reactive/package.json @@ -14,6 +14,7 @@ }, "starbeam:type": "library:public", "scripts": { + "test:specs": "vitest --run", "test:types": "tsc -b" }, "dependencies": { diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts index 0634294f..2a2bd89a 100644 --- a/packages/universal/reactive/src/primitives/formula.ts +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -1,23 +1,82 @@ import { readonly } from "@starbeam/core-utils"; -import type { - FormulaTag as IFormulaTag, - ReactiveFormula, - Stack, - Tag, -} from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; -import { FormulaTag } from "@starbeam/tags"; -import type { Marker } from "./marker.js"; -import type { Description } from "@starbeam/debug"; - -class FormulaValue implements ReactiveFormula { - declare readonly [TAG]: Tag; - readonly #initialized: Marker; - - constructor(description: Description) { - this.#initialized = Marker(description.); - readonly(this, TAG, FormulaTag.create()); - } - - read: (stack?: Stack | undefined) => IFormulaTag; +import { Desc, type Description } from "@starbeam/debug"; +import type { ReactiveFormula, Stack, Tag as ITag } from "@starbeam/interfaces"; +import { TAG, UNINITIALIZED } from "@starbeam/shared"; +import { Tag, type Timestamp, zero } from "@starbeam/tags"; +import { FormulaTag, NOW } from "@starbeam/tags"; + +import { getRuntime } from "../runtime.js"; +import type { PrimitiveOptions } from "./shared.js"; + +class FormulaImpl implements ReactiveFormula { + static create = ( + compute: () => T, + { description }: PrimitiveOptions + ): FormulaImpl => { + return new FormulaImpl(compute, Desc("formula", description)); + }; + + declare readonly [TAG]: ITag; + readonly #memo: Memo; + #children = new Set(); + #lastValidated: Timestamp = zero(); + + private constructor(compute: () => T, description: Description) { + this.#memo = new Memo(compute); + readonly( + this, + TAG, + FormulaTag.create(description, () => this.#children) + ); + } + + get current(): T { + return this.read(getRuntime().callerStack()); + } + + read(_stack?: Stack | undefined): T { + getRuntime().autotracking.consume(this[TAG]); + + const last = this.#memo.last; + + if (last === UNINITIALIZED || this.#isStale()) { + return this.#evaluate(); + } else { + return last; + } + } + + #evaluate(): T { + const done = getRuntime().autotracking.start(); + const value = this.#memo.compute(); + this.#children = done(); + this.#lastValidated = NOW.now; + getRuntime().subscriptions.update(this); + return value; + } + + #isStale(): boolean { + return Tag.lastUpdatedIn(this.#children).gt(this.#lastValidated); + } +} + +class Memo { + #value: T | UNINITIALIZED = UNINITIALIZED; + readonly #compute: () => T; + + constructor(compute: () => T) { + this.#compute = compute; + } + + compute(): T { + this.#value = this.#compute(); + return this.#value; + } + + get last(): T | UNINITIALIZED { + return this.#value; + } } + +export const Formula = FormulaImpl.create; +export type Formula = FormulaImpl; diff --git a/packages/universal/reactive/src/primitives/marker.ts b/packages/universal/reactive/src/primitives/marker.ts index 4a4c5aa0..f0ee0516 100644 --- a/packages/universal/reactive/src/primitives/marker.ts +++ b/packages/universal/reactive/src/primitives/marker.ts @@ -26,7 +26,7 @@ class MarkerImpl implements Tagged { this[TAG].freeze(); } - bump(caller = getRuntime().callerStack()): void { + mark(caller = getRuntime().callerStack()): void { this[TAG].update({ stack: caller, runtime: getRuntime() }); } } diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index 1b6a2669..8005d542 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -2,7 +2,7 @@ import type { Runtime } from "@starbeam/interfaces"; export const CONTEXT = { runtime: null as null | Runtime, -}; +}; export function defineRuntime(runtime: Runtime): void { CONTEXT.runtime = runtime; diff --git a/packages/universal/reactive/tests/.eslintrc.json b/packages/universal/reactive/tests/.eslintrc.json new file mode 100644 index 00000000..37ef5656 --- /dev/null +++ b/packages/universal/reactive/tests/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/loose"], + "files": ["**/*.ts"], + "parserOptions": { + "project": "packages/universal/reactive/tests/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/reactive/tests/.npmrc b/packages/universal/reactive/tests/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/reactive/tests/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/reactive/tests/package.json b/packages/universal/reactive/tests/package.json new file mode 100644 index 00000000..09086df5 --- /dev/null +++ b/packages/universal/reactive/tests/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@starbeam-tests/reactive", + "version": "1.0.0", + "type": "module", + "starbeam:type": "tests", + "scripts": { + "test:lint": "eslint" + }, + "dependencies": { + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", + "@starbeam/runtime": "workspace:^", + "@starbeam/shared": "workspace:^" + } +} diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index 3074c236..90cf9b34 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -20,7 +20,13 @@ export { type NotifyReady, Subscriptions, } from "./src/timeline/subscriptions.js"; +export { + MUTATIONS, + PUBLIC_TIMELINE, + type PublicTimeline, +} from "./src/timeline/tracker.js"; export { diff } from "./src/timeline/utils.js"; +export { TRACKING_STACK } from "./src/tracking-stack.js"; export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; export { getTag, Timestamp } from "@starbeam/tags"; diff --git a/packages/universal/runtime/src/timeline/frame.ts b/packages/universal/runtime/src/timeline/frame.ts index 259ab0a1..30dc9b9d 100644 --- a/packages/universal/runtime/src/timeline/frame.ts +++ b/packages/universal/runtime/src/timeline/frame.ts @@ -6,8 +6,7 @@ import type { } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; -import { CellTag, FormulaTag, getNow } from "@starbeam/tags"; -import { lastUpdatedInTaggedList } from "@starbeam/tags/src/tagged.js"; +import { CellTag, FormulaTag, getNow, getTag, Tag } from "@starbeam/tags"; import { isNotEqual, verified } from "@starbeam/verify"; import type { FrameStack } from "./frames.js"; @@ -26,7 +25,7 @@ export class Frame static create( this: void, value: T, - children: Set, + children: Set, finalized: Timestamp, description: Description ): Frame { @@ -78,7 +77,7 @@ export class Frame this: void, frame: Frame, value: T, - children: Set, + children: Set, finalized: Timestamp ): Frame { return frame.#update(value, children, finalized); @@ -87,14 +86,14 @@ export class Frame static updateChildren( this: void, frame: Frame, - children: Set + children: Set ): void { frame.#children = children; } #value: T | UNINITIALIZED; readonly #initialized: Marker; - #children: ReadonlySet; + #children: ReadonlySet; #finalized: Timestamp; readonly #description: Description; readonly [TAG]: FormulaTag; @@ -106,7 +105,7 @@ export class Frame lastUpdated: Timestamp; }; }, - children: Set, + children: Set, finalized: Timestamp, description: Description ) { @@ -116,7 +115,7 @@ export class Frame this.#finalized = finalized; this.#description = description; this[TAG] = FormulaTag.create(this.#description, () => [ - this.#initialized, + getTag(this.#initialized), ...this.#children, ]); } @@ -140,7 +139,7 @@ export class Frame } } - #update(value: T, children: Set, finalized: Timestamp): this { + #update(value: T, children: Set, finalized: Timestamp): this { if (Object.is(this.#value, UNINITIALIZED)) { this.#initialized[TAG].lastUpdated = finalized; } @@ -154,7 +153,7 @@ export class Frame validate(): FrameValidation> { if ( this.#value === UNINITIALIZED || - lastUpdatedInTaggedList([...this.#children]).gt(this.#finalized) + Tag.lastUpdatedIn(this.#children).gt(this.#finalized) ) { return { status: "invalid" }; } else { @@ -177,12 +176,12 @@ export class ActiveFrame { readonly #updating: Frame | null; readonly #prev: ActiveFrame | null; - readonly #children: Set; + readonly #children: Set; private constructor( updating: Frame | null, prev: ActiveFrame | null, - children: Set, + children: Set, readonly description: Description ) { this.#updating = updating; @@ -190,7 +189,7 @@ export class ActiveFrame { this.#children = children; } - add(child: Tagged): void { + add(child: interfaces.Tag): void { this.#children.add(child); } diff --git a/packages/universal/runtime/src/timeline/frames.ts b/packages/universal/runtime/src/timeline/frames.ts index 8df81706..5caf41fd 100644 --- a/packages/universal/runtime/src/timeline/frames.ts +++ b/packages/universal/runtime/src/timeline/frames.ts @@ -93,7 +93,7 @@ export class FrameStack { #didConsumeReactive(reactive: Tagged, caller: Stack): void { const frame = this.currentFrame; if (frame) { - frame.add(reactive); + frame.add(getTag(reactive)); return; } else { const delegatesTo = [...getTag(reactive).subscriptionTargets()]; diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index c90b6fdc..1b0fb5d3 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -56,3 +56,5 @@ export class PublicTimeline { return NOW.now; } } + +export const PUBLIC_TIMELINE = new PublicTimeline(); diff --git a/packages/universal/runtime/src/tracking-stack.ts b/packages/universal/runtime/src/tracking-stack.ts index da9b1d98..94f61af6 100644 --- a/packages/universal/runtime/src/tracking-stack.ts +++ b/packages/universal/runtime/src/tracking-stack.ts @@ -44,3 +44,5 @@ export class TrackingStack { export interface TrackingFrameData { readonly consumed: Set; } + +export const TRACKING_STACK = TrackingStack.create(); diff --git a/packages/universal/runtime/tests/package.json b/packages/universal/runtime/tests/package.json index 09111099..619a20f7 100644 --- a/packages/universal/runtime/tests/package.json +++ b/packages/universal/runtime/tests/package.json @@ -1,6 +1,6 @@ { "private": true, - "name": "@starbeam-tests/timeline", + "name": "@starbeam-tests/runtime", "version": "1.0.0", "type": "module", "starbeam:type": "tests", @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/shared": "workspace:^", - "@starbeam/runtime": "workspace:^" + "@starbeam/runtime": "workspace:^", + "@starbeam/shared": "workspace:^" } } diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index f06251a3..34abc778 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -1,6 +1,5 @@ import type { Description, UpdateOptions } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; import { type Timestamp, zero } from "./timestamp.js"; import { NOW } from "./timestamp.js"; @@ -131,23 +130,23 @@ export class StaticTag extends Tag implements interfaces.StaticTag { export class FormulaTag extends Tag implements interfaces.FormulaTag { static create( description: Description, - children: () => interfaces.List + children: () => interfaces.List ): FormulaTag { return new FormulaTag(description, children); } readonly type = "formula"; - readonly #children: () => interfaces.List; + readonly #children: () => interfaces.List; private constructor( description: Description, - children: () => interfaces.List + children: () => interfaces.List ) { super(description); this.#children = children; } - children(): readonly interfaces.Tagged[] { + children(): readonly interfaces.Tag[] { return [...this.#children()]; } @@ -164,42 +163,42 @@ export class FormulaTag extends Tag implements interfaces.FormulaTag { } override *dependencies(): interfaces.List { - yield* Tag.dependenciesInList(this.children().map((child) => child[TAG])); + yield* Tag.dependenciesInList(this.children()); } } export class DelegateTag extends Tag implements interfaces.DelegateTag { static create( description: Description, - targets: readonly interfaces.Tagged[] + targets: readonly interfaces.Tag[] ): DelegateTag { return new DelegateTag(description, targets); } readonly type = "delegate"; - readonly #targets: readonly interfaces.Tagged[]; + readonly #targets: readonly interfaces.Tag[]; private constructor( description: Description, - targets: readonly interfaces.Tagged[] + targets: readonly interfaces.Tag[] ) { super(description); this.#targets = targets; } - get targets(): readonly interfaces.Tagged[] { + get targets(): readonly interfaces.Tag[] { return this.#targets; } override *subscriptionTargets(): interfaces.List { for (const target of this.#targets) { - yield* target[TAG].subscriptionTargets(); + yield* target.subscriptionTargets(); } } override *dependencies(): interfaces.List { for (const target of this.#targets) { - yield* target[TAG].dependencies(); + yield* target.dependencies(); } } diff --git a/packages/universal/universal/package.json b/packages/universal/universal/package.json index 784cf614..af576f4c 100644 --- a/packages/universal/universal/package.json +++ b/packages/universal/universal/package.json @@ -29,9 +29,9 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", - "@starbeam/runtime": "workspace:^", "@starbeam/verify": "workspace:^" }, "devDependencies": { diff --git a/packages/universal/universal/src/reactive-core/formula/tracked-formula.ts b/packages/universal/universal/src/reactive-core/formula/tracked-formula.ts new file mode 100644 index 00000000..e69de29b From 88cdd5768bb07bfef1ff9e00ed5010184b778dda Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 26 Mar 2023 01:05:06 -0700 Subject: [PATCH 11/46] WIP: Migrating to new runtime For some reason, the iterable on collections isn't invalidating. The framework renderers also need to be updated. --- packages/preact/preact/src/frame.ts | 4 +- packages/preact/preact/tests/create.spec.ts | 4 +- packages/react/react/src/element.ts | 6 +- packages/universal/debug/src/timeline.ts | 21 ++- packages/universal/interfaces/index.d.ts | 10 +- .../universal/interfaces/src/protocol.d.ts | 2 +- .../universal/interfaces/src/runtime.d.ts | 20 +-- packages/universal/js/package.json | 3 +- packages/universal/js/src/array.ts | 2 +- packages/universal/js/src/collection.ts | 16 +-- packages/universal/js/src/decorator.ts | 2 +- packages/universal/js/src/iterable.ts | 48 +++---- packages/universal/js/src/map.ts | 2 +- packages/universal/js/src/object.ts | 2 +- packages/universal/js/src/set.ts | 2 +- packages/universal/modifier/src/modifier.ts | 4 +- .../universal/reactive/src/primitives/cell.ts | 7 +- .../reactive/src/primitives/formula.ts | 45 +++++- .../reactive/src/primitives/marker.ts | 5 +- packages/universal/runtime/index.ts | 6 +- packages/universal/runtime/package.json | 1 + packages/universal/runtime/src/define.ts | 72 ++++++++++ .../universal/runtime/src/timeline/api.ts | 1 + .../universal/runtime/src/timeline/frames.ts | 21 ++- .../runtime/src/timeline/subscriptions.ts | 4 + .../runtime/src/timeline/timeline.ts | 18 ++- .../universal/runtime/src/timeline/tracker.ts | 17 ++- .../universal/runtime/src/tracking-stack.ts | 27 +--- .../universal/runtime/tests/consume.spec.ts | 72 ++++++---- packages/universal/runtime/tests/package.json | 1 + .../universal/runtime/tests/protocol.spec.ts | 56 ++++---- .../{pollable.spec.ts => subscribing.spec.ts} | 49 +++---- .../{subscription.ts => subscription.spec.ts} | 40 ++---- .../runtime/tests/support/mini-reactives.ts | 132 ------------------ packages/universal/shared/src/now.ts | 2 +- packages/universal/tags/index.ts | 1 + packages/universal/tags/src/tag.ts | 24 ++-- packages/universal/tags/src/tagged.ts | 6 + packages/universal/universal/index.ts | 9 +- .../universal/universal/src/debug-renderer.ts | 6 +- .../universal/src/reactive-core/delegate.ts | 6 +- .../src/reactive-core/formula/formula.ts | 4 +- .../reactive-core/formula/polled-formula.ts | 4 +- .../src/reactive-core/formula/setups.ts | 12 +- .../universal/src/reactive-core/marker.ts | 50 ------- .../src/reactive-core/resource/run.ts | 2 +- .../universal/src/reactive-core/variants.ts | 50 +++---- packages/universal/universal/src/runtime.ts | 44 ------ .../universal/universal/tests/factory.spec.ts | 2 +- .../universal/universal/tests/formula.spec.ts | 2 +- .../universal/tests/resource.spec.ts | 4 +- .../universal/universal/tests/setup.spec.ts | 5 +- .../universal/tests/variants.spec.ts | 29 ++-- packages/x/store/src/flat.ts | 2 +- pnpm-lock.yaml | 22 +++ 55 files changed, 459 insertions(+), 549 deletions(-) create mode 100644 packages/universal/runtime/src/define.ts rename packages/universal/runtime/tests/{pollable.spec.ts => subscribing.spec.ts} (71%) rename packages/universal/runtime/tests/{subscription.ts => subscription.spec.ts} (50%) delete mode 100644 packages/universal/runtime/tests/support/mini-reactives.ts delete mode 100644 packages/universal/universal/src/reactive-core/marker.ts delete mode 100644 packages/universal/universal/src/runtime.ts diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index 813ffc07..71e0ba6b 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -4,7 +4,7 @@ import type { InternalComponent } from "@starbeam/preact-utils"; import { type ActiveFrame, type Frame, - TIMELINE, + PUBLIC_TIMELINE, type Unsubscribe, } from "@starbeam/runtime"; import { expected, isPresent, verify } from "@starbeam/verify"; @@ -99,7 +99,7 @@ export class ComponentFrame { this.#active = null; if (subscription) { - this.#subscription = TIMELINE.on.change(frame, subscription); + this.#subscription = PUBLIC_TIMELINE.on.change(frame, subscription); } return frame; diff --git a/packages/preact/preact/tests/create.spec.ts b/packages/preact/preact/tests/create.spec.ts index b4a5c6f6..6eea9623 100644 --- a/packages/preact/preact/tests/create.spec.ts +++ b/packages/preact/preact/tests/create.spec.ts @@ -65,7 +65,9 @@ const INITIAL_COUNT = 0; const INCREMENT = 1; function ReactiveObject(): { cell: Cell; increment: () => void } { - const cell = Cell(INITIAL_COUNT, `ReactiveObject #${++nextId}`); + const cell = Cell(INITIAL_COUNT, { + description: `ReactiveObject #${++nextId}`, + }); function increment(): void { cell.set(cell.current + INCREMENT); diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 06891d6d..394b61e4 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -5,7 +5,7 @@ import { type CleanupTarget, LIFETIME, type OnCleanup, - TIMELINE, + PUBLIC_TIMELINE, type Unsubscribe, } from "@starbeam/runtime"; import { @@ -201,7 +201,7 @@ export class ReactiveElement implements CleanupTarget { } static subscribe(element: ReactiveElement, reactive: Tagged): void { - const subscription = TIMELINE.on.change(reactive, element.notify); + const subscription = PUBLIC_TIMELINE.on.change(reactive, element.notify); element.on.cleanup(subscription); } @@ -264,7 +264,7 @@ export class ReactiveElement implements CleanupTarget { this.notify(); }; - const unsubscribe = TIMELINE.on.change(resource, this.notify); + const unsubscribe = PUBLIC_TIMELINE.on.change(resource, this.notify); LIFETIME.on.cleanup(resource, unsubscribe); diff --git a/packages/universal/debug/src/timeline.ts b/packages/universal/debug/src/timeline.ts index 0afcc94a..e12a3147 100644 --- a/packages/universal/debug/src/timeline.ts +++ b/packages/universal/debug/src/timeline.ts @@ -2,7 +2,6 @@ import type { CellTag, Diff, FormulaTag, - Frame, Stack, Tag, Tagged, @@ -60,26 +59,26 @@ export class CellUpdateOperation extends LeafOperation { interface FrameConsumeInfo extends OperationInfo { readonly diff: Diff; - readonly frame: Frame; + readonly formula: FormulaTag; } export class FrameConsumeOperation extends LeafOperation { readonly #diff: Diff; - readonly #frame: Frame; + readonly #formula: FormulaTag; readonly type = "frame:consume"; constructor(data: FrameConsumeInfo) { super(data); this.#diff = data.diff; - this.#frame = data.frame; + this.#formula = data.formula; } get diff(): Diff { return this.#diff; } - get frame(): Frame { - return this.#frame; + get formula(): FormulaTag { + return this.#formula; } } export class MutationLog { @@ -307,8 +306,8 @@ export class DebugTimeline { this.#consumeCell(internals, caller); } - consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { - this.#consumeFrame(frame, diff, caller); + consumeFrame(formula: FormulaTag, diff: Diff, caller: Stack): void { + this.#consumeFrame(formula, diff, caller); } updateCell(cell: CellTag, caller: Stack): void { @@ -321,14 +320,14 @@ export class DebugTimeline { ); } - #consumeFrame(frame: Frame, diff: Diff, caller: Stack): void { + #consumeFrame(formula: FormulaTag, diff: Diff, caller: Stack): void { this.#add( new FrameConsumeOperation({ at: this.#timestamp.now(), - for: frame[TAG], + for: formula, diff, caller, - frame, + formula, }) ); } diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index cab01ea7..176eea22 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -44,9 +44,15 @@ export type { Tagged, TagMethods, TagType, - UpdateOptions, } from "./src/protocol.js"; -export type { Runtime } from "./src/runtime.js"; +export type { + AutotrackingRuntime, + DeprecatedTimeline, + Runtime, + RuntimeFrame, + SubscriptionRuntime, + UpdateOptions, +} from "./src/runtime.js"; export type { DisplayParts, Stack, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 06166865..b7ff7cbe 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -16,7 +16,7 @@ export type List = Iterable | T[] | readonly T[]; export class TagMethods { readonly id: ReactiveId; readonly lastUpdated: Timestamp; - readonly dependencies: () => List; + readonly dependencies: () => readonly CellTag[]; readonly description: Description; match(matcher: Matcher): Tag; subscriptionTargets(): List; diff --git a/packages/universal/interfaces/src/runtime.d.ts b/packages/universal/interfaces/src/runtime.d.ts index 3f8ad053..4356cadc 100644 --- a/packages/universal/interfaces/src/runtime.d.ts +++ b/packages/universal/interfaces/src/runtime.d.ts @@ -1,18 +1,20 @@ import type { Unsubscribe } from "./aliases.js"; -import type { Description } from "./description.js"; -import type { CellTag, Tag, Tagged } from "./protocol.js"; +import type { CellTag, FormulaTag, Tag } from "./protocol.js"; import type { Stack as CallStack } from "./stack.js"; import type { Timestamp } from "./timestamp.js"; +/** + * @deprecated + */ +export interface DeprecatedTimeline { + bumpCell: (cell: CellTag, caller: CallStack) => Timestamp; + didConsumeCell: (cell: CellTag, caller: CallStack) => void; +} + export interface Runtime { callerStack: () => CallStack; - didConsumeCell: (cell: Tagged, caller: CallStack) => void; - bumpCell: (cell: CellTag, caller: CallStack) => Timestamp; - creatingFrame: (description: Description) => ActiveRuntimeFrame; - updatingFrame: ( - description: Description, - frame: RuntimeFrame - ) => ActiveRuntimeFrame; + /** @deprecated */ + readonly timeline: DeprecatedTimeline; readonly subscriptions: SubscriptionRuntime; readonly autotracking: AutotrackingRuntime; } diff --git a/packages/universal/js/package.json b/packages/universal/js/package.json index 1f17b495..50c8ef45 100644 --- a/packages/universal/js/package.json +++ b/packages/universal/js/package.json @@ -28,9 +28,10 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", - "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/universal/js/src/array.ts b/packages/universal/js/src/array.ts index df8624af..21b1203a 100644 --- a/packages/universal/js/src/array.ts +++ b/packages/universal/js/src/array.ts @@ -6,7 +6,7 @@ // and it will blow up in JS in exactly the same way, so it is safe to assume // that properties within the getter have the correct type in TS. -import { type Description, callerStack } from "@starbeam/debug"; +import { callerStack, type Description } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; import { Collection } from "./collection.js"; diff --git a/packages/universal/js/src/collection.ts b/packages/universal/js/src/collection.ts index f9df59aa..afe3fdc3 100644 --- a/packages/universal/js/src/collection.ts +++ b/packages/universal/js/src/collection.ts @@ -1,6 +1,6 @@ import type { Description, Stack } from "@starbeam/debug"; +import { Cell, Marker } from "@starbeam/reactive"; import { taggedDescription } from "@starbeam/tags"; -import { Cell, Marker } from "@starbeam/universal"; import { expected, isPresent, verified } from "@starbeam/verify"; class ItemState { @@ -18,7 +18,7 @@ class ItemState { .key(member) .asImplementation({ reason: "initialization tracking" }), }), - Marker(description.key(member)) + Marker({ description: description.key(member) }) ); } @@ -49,12 +49,12 @@ class ItemState { read(caller: Stack): void { this.#present.read(caller); - this.#value.consume(caller); + this.#value.read(caller); } update(caller: Stack): void { this.#present.current = true; - this.#value.update(caller); + this.#value.mark(caller); } } @@ -199,7 +199,7 @@ export class Collection { caller: Stack ): Item { if (this.#iteration === undefined) { - this.#iteration = Marker(this.#description); + this.#iteration = Marker({ description: this.#description }); } let item: Item; @@ -217,12 +217,12 @@ export class Collection { iterateKeys(caller: Stack): void { if (this.#iteration === undefined) { - this.#iteration = Marker(this.#description); + this.#iteration = Marker({ description: this.#description }); } // remember that we iterated this collection so that consumers of the // iteration detect changes to the collection itself. - this.#iteration.consume(caller); + this.#iteration.read(caller); } set( @@ -267,6 +267,6 @@ export class Collection { // of Starbeam can used keyed collections, we should make sure the // bookkeeping would actually pay for itself before spending the time to // implement it. - this.#iteration.update(caller); + this.#iteration.mark(caller); } } diff --git a/packages/universal/js/src/decorator.ts b/packages/universal/js/src/decorator.ts index eea20fff..075143ba 100644 --- a/packages/universal/js/src/decorator.ts +++ b/packages/universal/js/src/decorator.ts @@ -33,7 +33,7 @@ export const cached = ( formula = Formula( // eslint-disable-next-line () => get.call(this), - `computing ${String(key)}` + { description: `computing ${String(key)}` } ); CACHED.set(this, formula); } diff --git a/packages/universal/js/src/iterable.ts b/packages/universal/js/src/iterable.ts index 687784b6..52073e04 100644 --- a/packages/universal/js/src/iterable.ts +++ b/packages/universal/js/src/iterable.ts @@ -1,7 +1,7 @@ import type { Stack } from "@starbeam/debug"; import { callerStack, type Description } from "@starbeam/debug"; +import { Cell, type Equality, Marker } from "@starbeam/reactive"; import { UNINITIALIZED } from "@starbeam/shared"; -import { Cell, type Equality, Marker } from "@starbeam/universal"; class Entry { readonly #initialized: Cell; @@ -112,13 +112,13 @@ export class ReactiveMap implements Map { private constructor(description: Description, equality: Equality) { this.#description = description; this.#equality = equality; - this.#keys = Marker(description.key("keys")); - this.#values = Marker(description.key("values")); + this.#keys = Marker({ description: description.key("keys") }); + this.#values = Marker({ description: description.key("values") }); } get size(): number { const caller = callerStack(); - this.#keys.consume(caller); + this.#keys.read(caller); let size = 0; @@ -139,8 +139,8 @@ export class ReactiveMap implements Map { const caller = callerStack(); if (this.#entries.size > EMPTY_MAP_SIZE) { this.#entries.clear(); - this.#keys.update(caller); - this.#values.update(caller); + this.#keys.mark(caller); + this.#values.mark(caller); } } @@ -153,8 +153,8 @@ export class ReactiveMap implements Map { if (disposition === "deleted") { this.#entries.delete(key); - this.#keys.update(caller); - this.#values.update(caller); + this.#keys.mark(caller); + this.#values.mark(caller); return true; } } @@ -164,8 +164,8 @@ export class ReactiveMap implements Map { *entries(): IterableIterator<[K, V]> { const caller = callerStack(); - this.#keys.consume(caller); - this.#values.consume(caller); + this.#keys.read(caller); + this.#values.read(caller); for (const [key, value] of this.#iterate(caller)) { yield [key, value.get(caller) as V]; @@ -195,8 +195,8 @@ export class ReactiveMap implements Map { thisArg?: unknown ): void { const caller = callerStack(); - this.#keys.consume(caller); - this.#values.consume(caller); + this.#keys.read(caller); + this.#values.read(caller); for (const [key, entry] of this.#entries) { callbackfn.call(thisArg, entry.get(caller) as V, key, this); @@ -224,7 +224,7 @@ export class ReactiveMap implements Map { *keys(): IterableIterator { const caller = callerStack(); - this.#keys.consume(caller); + this.#keys.read(caller); for (const [key] of this.#iterate(caller)) { yield key; @@ -238,11 +238,11 @@ export class ReactiveMap implements Map { const disposition = entry.set(value, caller); if (disposition === "initialized") { - this.#keys.update(caller); + this.#keys.mark(caller); } if (disposition === "initialized" || disposition === "updated") { - this.#values.update(caller); + this.#values.mark(caller); } return this; @@ -252,7 +252,7 @@ export class ReactiveMap implements Map { // add an extra frame for the internal JS call to .next() const caller = callerStack(EXTRA_CALLER_FRAME); - this.#values.consume(caller); + this.#values.read(caller); for (const [, value] of this.#iterate(caller)) { yield value.get(caller) as V; @@ -278,13 +278,13 @@ export class ReactiveSet implements Set { private constructor(description: Description, equality: Equality) { this.#description = description; this.#equality = equality; - this.#values = Marker(description.key("values")); + this.#values = Marker({ description: description.key("values") }); } get size(): number { const caller = callerStack(); - this.#values.consume(caller); + this.#values.read(caller); let size = 0; @@ -306,7 +306,7 @@ export class ReactiveSet implements Set { if (!entry.isPresent(caller)) { this.#entries.set(value, entry); - this.#values.update(caller); + this.#values.mark(caller); entry.set(value, caller); } @@ -318,7 +318,7 @@ export class ReactiveSet implements Set { if (this.#entries.size > EMPTY_MAP_SIZE) { this.#entries.clear(); - this.#values.update(caller); + this.#values.mark(caller); } } @@ -331,7 +331,7 @@ export class ReactiveSet implements Set { const disposition = entry.delete(caller); if (disposition === "deleted") { - this.#values.update(caller); + this.#values.mark(caller); this.#entries.delete(value); return true; } @@ -343,7 +343,7 @@ export class ReactiveSet implements Set { *entries(): IterableIterator<[T, T]> { const caller = callerStack(); - this.#values.consume(caller); + this.#values.read(caller); for (const [value, entry] of this.#iterate(caller)) { yield [value, entry.get(caller) as T]; @@ -356,7 +356,7 @@ export class ReactiveSet implements Set { ): void { const caller = callerStack(); - this.#values.consume(caller); + this.#values.read(caller); for (const [value] of this.#iterate(caller)) { callbackfn.call(thisArg, value, value, this); @@ -380,7 +380,7 @@ export class ReactiveSet implements Set { *keys(): IterableIterator { const caller = callerStack(); - this.#values.consume(caller); + this.#values.read(caller); for (const [value] of this.#iterate(caller)) { yield value; diff --git a/packages/universal/js/src/map.ts b/packages/universal/js/src/map.ts index 02535ed9..eca46a60 100644 --- a/packages/universal/js/src/map.ts +++ b/packages/universal/js/src/map.ts @@ -1,4 +1,4 @@ -import { type Description, callerStack } from "@starbeam/debug"; +import { callerStack, type Description } from "@starbeam/debug"; import type { Equality } from "@starbeam/universal"; import { Collection } from "./collection.js"; diff --git a/packages/universal/js/src/object.ts b/packages/universal/js/src/object.ts index 88995d78..ce341082 100644 --- a/packages/universal/js/src/object.ts +++ b/packages/universal/js/src/object.ts @@ -1,4 +1,4 @@ -import { type Description, callerStack } from "@starbeam/debug"; +import { callerStack, type Description } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; import { Collection } from "./collection.js"; diff --git a/packages/universal/js/src/set.ts b/packages/universal/js/src/set.ts index 20d3dd2b..6ff68c8f 100644 --- a/packages/universal/js/src/set.ts +++ b/packages/universal/js/src/set.ts @@ -1,4 +1,4 @@ -import { type Description, callerStack } from "@starbeam/debug"; +import { callerStack, type Description } from "@starbeam/debug"; import { Collection } from "./collection.js"; diff --git a/packages/universal/modifier/src/modifier.ts b/packages/universal/modifier/src/modifier.ts index c31fc522..7db028e7 100644 --- a/packages/universal/modifier/src/modifier.ts +++ b/packages/universal/modifier/src/modifier.ts @@ -2,7 +2,7 @@ import type { anydom } from "@domtree/flavors"; import { type Description, REUSE_ID } from "@starbeam/debug"; import type { Tagged } from "@starbeam/interfaces"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; -import { DelegateTag } from "@starbeam/tags"; +import { DelegateTag, getTag } from "@starbeam/tags"; import { Cell } from "@starbeam/universal"; import { expected, isPresent, verified, verify } from "@starbeam/verify"; @@ -35,7 +35,7 @@ export function ElementPlaceholder( REFS.set(ref, elementCell); return { - [TAG]: DelegateTag.create(description, [elementCell]), + [TAG]: DelegateTag.create(description, [getTag(elementCell)]), initialize(value: anydom.Element): void { const element = verified(REFS.get(ref), isPresent); diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index 841b2c28..60df6e66 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -13,7 +13,7 @@ export class CellImpl implements ReactiveCell { value: T, { description, equals = Object.is }: CellOptions = {} ): CellImpl => { - return new CellImpl(value, equals, Desc("static", description)); + return new CellImpl(value, equals, Desc("cell", description)); }; #value: T; @@ -38,8 +38,9 @@ export class CellImpl implements ReactiveCell { this.set(value, getRuntime().callerStack()); } - read(caller = getRuntime().callerStack()): T { - getRuntime().didConsumeCell(this, caller); + read(_caller = getRuntime().callerStack()): T { + // getRuntime().timeline.didConsumeCell(this[TAG], caller); + getRuntime().autotracking.consume(this[TAG]); return this.#value; } diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts index 2a2bd89a..0ed85fd6 100644 --- a/packages/universal/reactive/src/primitives/formula.ts +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -1,6 +1,11 @@ import { readonly } from "@starbeam/core-utils"; import { Desc, type Description } from "@starbeam/debug"; -import type { ReactiveFormula, Stack, Tag as ITag } from "@starbeam/interfaces"; +import type { + Reactive, + ReactiveFormula, + Stack, + Tag as ITag, +} from "@starbeam/interfaces"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; import { Tag, type Timestamp, zero } from "@starbeam/tags"; import { FormulaTag, NOW } from "@starbeam/tags"; @@ -8,15 +13,37 @@ import { FormulaTag, NOW } from "@starbeam/tags"; import { getRuntime } from "../runtime.js"; import type { PrimitiveOptions } from "./shared.js"; +interface FormulaFn extends Reactive { + (): T; +} + class FormulaImpl implements ReactiveFormula { static create = ( compute: () => T, - { description }: PrimitiveOptions - ): FormulaImpl => { - return new FormulaImpl(compute, Desc("formula", description)); + { description }: PrimitiveOptions = {} + ): FormulaFn => { + const formula = new FormulaImpl(compute, Desc("formula", description)); + + const fn = (): T => { + return formula.read(getRuntime().callerStack()); + }; + + Object.defineProperties(fn, { + current: { + get: fn, + }, + [TAG]: { + get: () => formula[TAG], + }, + read: { + value: fn, + }, + }); + + return fn as FormulaFn; }; - declare readonly [TAG]: ITag; + declare readonly [TAG]: FormulaTag; readonly #memo: Memo; #children = new Set(); #lastValidated: Timestamp = zero(); @@ -35,8 +62,12 @@ class FormulaImpl implements ReactiveFormula { } read(_stack?: Stack | undefined): T { + const value = this.#value(); getRuntime().autotracking.consume(this[TAG]); + return value; + } + #value(): T { const last = this.#memo.last; if (last === UNINITIALIZED || this.#isStale()) { @@ -51,7 +82,7 @@ class FormulaImpl implements ReactiveFormula { const value = this.#memo.compute(); this.#children = done(); this.#lastValidated = NOW.now; - getRuntime().subscriptions.update(this); + getRuntime().subscriptions.update(this[TAG]); return value; } @@ -79,4 +110,4 @@ class Memo { } export const Formula = FormulaImpl.create; -export type Formula = FormulaImpl; +export type Formula = FormulaFn; diff --git a/packages/universal/reactive/src/primitives/marker.ts b/packages/universal/reactive/src/primitives/marker.ts index f0ee0516..fff68306 100644 --- a/packages/universal/reactive/src/primitives/marker.ts +++ b/packages/universal/reactive/src/primitives/marker.ts @@ -8,7 +8,10 @@ import { getRuntime } from "../runtime.js"; import type { PrimitiveOptions } from "./shared.js"; class MarkerImpl implements Tagged { - static create(this: void, { description }: PrimitiveOptions): MarkerImpl { + static create( + this: void, + { description }: PrimitiveOptions = {} + ): MarkerImpl { return new MarkerImpl(Desc("cell", description)); } diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index 90cf9b34..93ec8cf6 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -10,7 +10,6 @@ export { type OnCleanup, } from "./src/lifetime/api.js"; export type { Unsubscribe } from "./src/lifetime/object-lifetime.js"; -export { TIMELINE } from "./src/timeline/api.js"; export { ActiveFrame, Frame, @@ -21,14 +20,15 @@ export { Subscriptions, } from "./src/timeline/subscriptions.js"; export { - MUTATIONS, PUBLIC_TIMELINE, type PublicTimeline, + SUBSCRIPTION_RUNTIME, } from "./src/timeline/tracker.js"; export { diff } from "./src/timeline/utils.js"; -export { TRACKING_STACK } from "./src/tracking-stack.js"; +export { AUTOTRACKING_RUNTIME } from "./src/tracking-stack.js"; export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; export { getTag, Timestamp } from "@starbeam/tags"; export type { interfaces }; import type * as interfaces from "@starbeam/interfaces"; +export { RUNTIME } from "./src/define.js"; diff --git a/packages/universal/runtime/package.json b/packages/universal/runtime/package.json index 3017e4b7..9149f0c4 100644 --- a/packages/universal/runtime/package.json +++ b/packages/universal/runtime/package.json @@ -28,6 +28,7 @@ "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", "@starbeam/verify": "workspace:^" diff --git a/packages/universal/runtime/src/define.ts b/packages/universal/runtime/src/define.ts new file mode 100644 index 00000000..57ef6642 --- /dev/null +++ b/packages/universal/runtime/src/define.ts @@ -0,0 +1,72 @@ +import { callerStack } from "@starbeam/debug"; +import type { + AutotrackingRuntime, + Runtime as IRuntime, + Stack, + SubscriptionRuntime, +} from "@starbeam/interfaces"; +import { defineRuntime } from "@starbeam/reactive"; + +import { TIMELINE } from "./timeline/api.js"; +import { SUBSCRIPTION_RUNTIME } from "./timeline/tracker.js"; +import { AUTOTRACKING_RUNTIME } from "./tracking-stack.js"; + +type Timeline = typeof TIMELINE; + +class Runtime implements IRuntime { + static default(): Runtime { + return new Runtime(TIMELINE, SUBSCRIPTION_RUNTIME, AUTOTRACKING_RUNTIME); + } + + static single( + runtime: Timeline & SubscriptionRuntime & AutotrackingRuntime + ): Runtime { + return new Runtime(runtime, runtime, runtime); + } + + static create({ + timeline, + subscriptions, + autotracking, + }: { + timeline: Timeline; + subscriptions: SubscriptionRuntime; + autotracking: AutotrackingRuntime; + }): Runtime { + return new Runtime(timeline, subscriptions, autotracking); + } + + readonly #timeline: Timeline; + readonly #subscriptions: SubscriptionRuntime; + readonly #autotracking: AutotrackingRuntime; + + private constructor( + timeline: Timeline, + subscription: SubscriptionRuntime, + autotracking: AutotrackingRuntime + ) { + this.#timeline = timeline; + this.#subscriptions = subscription; + this.#autotracking = autotracking; + } + + get timeline(): Timeline { + return this.#timeline; + } + + get subscriptions(): SubscriptionRuntime { + return this.#subscriptions; + } + + get autotracking(): AutotrackingRuntime { + return this.#autotracking; + } + + callerStack(): Stack { + return callerStack(); + } +} + +export const RUNTIME = Runtime.default(); + +defineRuntime(RUNTIME); diff --git a/packages/universal/runtime/src/timeline/api.ts b/packages/universal/runtime/src/timeline/api.ts index 37f37271..5a752fdf 100644 --- a/packages/universal/runtime/src/timeline/api.ts +++ b/packages/universal/runtime/src/timeline/api.ts @@ -1,3 +1,4 @@ import { Timeline } from "./timeline.js"; +/** @deprecated */ export const TIMELINE = Timeline.create(); diff --git a/packages/universal/runtime/src/timeline/frames.ts b/packages/universal/runtime/src/timeline/frames.ts index 5caf41fd..b141907e 100644 --- a/packages/universal/runtime/src/timeline/frames.ts +++ b/packages/universal/runtime/src/timeline/frames.ts @@ -1,7 +1,6 @@ import type { DebugTimeline, Stack } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { CellTag, Tagged } from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; +import type { CellTag } from "@starbeam/interfaces"; import { getTag } from "@starbeam/tags"; import { ActiveFrame, type Frame } from "./frame.js"; @@ -13,18 +12,14 @@ export class FrameStack { #subscriptions: Subscriptions; #timeline: Timeline; - static didConsumeCell( - frames: FrameStack, - reactive: Tagged, - caller: Stack - ): void { - frames.#debug.consumeCell(reactive[TAG], caller); - frames.#didConsumeReactive(reactive, caller); + static didConsumeCell(frames: FrameStack, tag: CellTag, caller: Stack): void { + frames.#debug.consumeCell(tag, caller); + frames.#didConsumeReactive(tag, caller); } static didConsumeFrame( frames: FrameStack, - frame: interfaces.Frame, + frame: interfaces.FormulaTag, diff: interfaces.Diff, caller: Stack ): void { @@ -90,13 +85,13 @@ export class FrameStack { return this.#start(description) as ActiveFrame; } - #didConsumeReactive(reactive: Tagged, caller: Stack): void { + #didConsumeReactive(tag: interfaces.Tag, caller: Stack): void { const frame = this.currentFrame; if (frame) { - frame.add(getTag(reactive)); + frame.add(tag); return; } else { - const delegatesTo = [...getTag(reactive).subscriptionTargets()]; + const delegatesTo = [...tag.subscriptionTargets()]; for (const target of delegatesTo) { if (target.type === "cell") { diff --git a/packages/universal/runtime/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts index f02f6abc..9fdc5ef3 100644 --- a/packages/universal/runtime/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -148,6 +148,10 @@ class SubscriberMap { class ReactiveSubscription { static create(target: Tag): ReactiveSubscription { + if (typeof target.dependencies !== "function") { + console.log(target); + throw Error("Reactive subscriptions must be created with tags"); + } const deps = new Set(target.dependencies()); return new ReactiveSubscription(deps); } diff --git a/packages/universal/runtime/src/timeline/timeline.ts b/packages/universal/runtime/src/timeline/timeline.ts index 29a13c95..1fa32038 100644 --- a/packages/universal/runtime/src/timeline/timeline.ts +++ b/packages/universal/runtime/src/timeline/timeline.ts @@ -36,7 +36,7 @@ type TimelineOp = "consumed" | "bumped" | "evaluating" | "initial"; * Whenever a {@linkcode MutableInternals} is updated, the timeline will notify all subscribers of * reactives that depend on that dependency. */ -export class Timeline { +export class Timeline implements interfaces.DeprecatedTimeline { #debugTimeline: DebugTimeline | null = null; readonly #frame: FrameStack; @@ -120,6 +120,15 @@ export class Timeline { } } + bumpCell(mutable: interfaces.CellTag, caller: Stack): interfaces.Timestamp { + return this.bump(mutable, caller); + } + + didConsumeCell(cell: interfaces.CellTag, caller: Stack): void { + this.#adjustTimestamp("consumed"); + FrameStack.didConsumeCell(this.#frame, cell, caller); + } + bump(mutable: interfaces.CellTag, caller: Stack): interfaces.Timestamp { const now = this.#adjustTimestamp("bumped"); @@ -131,18 +140,13 @@ export class Timeline { return now; } - didConsumeCell(cell: Tagged, caller: Stack): void { - this.#adjustTimestamp("consumed"); - FrameStack.didConsumeCell(this.#frame, cell, caller); - } - didConsumeFrame( frame: interfaces.Frame, diff: interfaces.Diff, caller: Stack ): void { this.#adjustTimestamp("consumed"); - FrameStack.didConsumeFrame(this.#frame, frame, diff, caller); + FrameStack.didConsumeFrame(this.#frame, getTag(frame), diff, caller); } next(): interfaces.Timestamp { diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index 1b0fb5d3..6f9e95bc 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -1,6 +1,13 @@ -import type { CellTag, Tag, Tagged, Unsubscribe } from "@starbeam/interfaces"; +import type { + CellTag, + FormulaTag, + SubscriptionRuntime, + Tag, + Tagged, + Unsubscribe, +} from "@starbeam/interfaces"; import { getTag, type Timestamp } from "@starbeam/tags"; -import { type FormulaTag, NOW } from "@starbeam/tags"; +import { NOW } from "@starbeam/tags"; import { type NotifyReady, Subscriptions } from "./subscriptions.js"; @@ -16,7 +23,7 @@ enum Phase { * `Tagged` values. Reactive implementations that use `FormulaTag` are * responsible for notifying the timeline when their dependencies change. */ -class Mutations { +class Mutations implements SubscriptionRuntime { readonly #subscriptions = Subscriptions.create(); readonly #lastPhase: Phase = Phase.read; @@ -43,12 +50,12 @@ class Mutations { } } -export const MUTATIONS = new Mutations(); +export const SUBSCRIPTION_RUNTIME = new Mutations(); export class PublicTimeline { readonly on = { change: (target: Tagged, ready: NotifyReady): Unsubscribe => { - return MUTATIONS.subscribe(getTag(target), ready); + return SUBSCRIPTION_RUNTIME.subscribe(getTag(target), ready); }, }; diff --git a/packages/universal/runtime/src/tracking-stack.ts b/packages/universal/runtime/src/tracking-stack.ts index 94f61af6..37a8be57 100644 --- a/packages/universal/runtime/src/tracking-stack.ts +++ b/packages/universal/runtime/src/tracking-stack.ts @@ -1,34 +1,21 @@ -import { iterableHasItems } from "@starbeam/core-utils"; -import type { Tag } from "@starbeam/interfaces"; +import type { AutotrackingRuntime, Tag } from "@starbeam/interfaces"; -export class TrackingStack { +export class TrackingStack implements AutotrackingRuntime { static create(): TrackingStack { return new TrackingStack(); } #current: TrackingFrameData | undefined; - start({ - intoTag, - }: { - intoTag: (tags: Set) => T; - }): () => T { + start(): () => Set { const frame: TrackingFrameData = { consumed: new Set() }; const parent = this.#current; this.#current = frame; return () => { - const tag = intoTag(frame.consumed); - - if (parent) { - this.#current = parent; - - if (iterableHasItems(tag.dependencies())) { - parent.consumed.add(tag); - } - } - - return tag; + const consumed = frame.consumed; + this.#current = parent; + return consumed; }; } @@ -45,4 +32,4 @@ export interface TrackingFrameData { readonly consumed: Set; } -export const TRACKING_STACK = TrackingStack.create(); +export const AUTOTRACKING_RUNTIME = TrackingStack.create(); diff --git a/packages/universal/runtime/tests/consume.spec.ts b/packages/universal/runtime/tests/consume.spec.ts index 0db76ef1..4a79e706 100644 --- a/packages/universal/runtime/tests/consume.spec.ts +++ b/packages/universal/runtime/tests/consume.spec.ts @@ -1,37 +1,57 @@ -import { descriptionFrom, Stack } from "@starbeam/debug"; +import { Desc, Stack } from "@starbeam/debug"; +import { Cell, Formula, getRuntime, Marker } from "@starbeam/reactive"; +import { getTag } from "@starbeam/runtime"; import { getID } from "@starbeam/shared"; -import { TIMELINE } from "@starbeam/runtime"; +import { FormulaTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; -import { Cell, Formula, Marker } from "./support/mini-reactives.js"; import { Staleness } from "./support/testing.js"; +const RUNTIME = getRuntime(); + describe("consumption", () => { + test("the basics", () => { + const number = Cell(1); + const double = Formula(() => number.current * 2); + + expect(double.current).toBe(2); + + number.current++; + + expect(double.current).toBe(4); + }); + test("in the context of a frame", () => { - const { update, instance } = Marker(); + const instance = Marker(); const id = getID(); const here = Stack.fromCaller(-1); - const frame = TIMELINE.frame.evaluate( - () => { - TIMELINE.didConsumeCell(instance, here); - }, - { - description: descriptionFrom({ - id, - type: "formula", - api: "Formula", - }), - } - ); + const done = RUNTIME.autotracking.start(); + RUNTIME.autotracking.consume(getTag(instance)); + const tags = done(); + const tag = FormulaTag.create(Desc("formula"), () => tags); + // const frame = TIMELINE.frame.evaluate( + // () => { + // TIMELINE.didConsumeCell(getTag(instance), here); + // }, + // { + // description: descriptionFrom({ + // id, + // type: "formula", + // api: "Formula", + // }), + // } + // ); const stale = new Staleness(); - TIMELINE.on.change(frame, () => { + RUNTIME.subscriptions.subscribe(tag, () => { stale.invalidate(); }); stale.expect("fresh"); - stale.expect(update, "stale"); + stale.expect(() => { + instance.mark(); + }, "stale"); }); test("nested frames (with updates)", () => { @@ -44,38 +64,38 @@ describe("consumption", () => { const doubleC = Formula(() => cellC.current * 2); const sum = Formula(() => { - const abSum = doubleA.poll() + doubleB.poll(); + const abSum = doubleA.current + doubleB.current; if (abSum > 15) { - return abSum + doubleC.poll(); + return abSum + doubleC.current; } else { return abSum; } }); const stale = new Staleness(); - const unsubscribe = TIMELINE.on.change(sum.frame, () => { + const unsubscribe = RUNTIME.subscriptions.subscribe(getTag(sum), () => { stale.invalidate(); }); stale.expect("fresh"); - expect(sum.poll()).toBe(6); + expect(sum.current).toBe(6); stale.expect(() => (cellA.current += 2), "stale"); - expect(sum.poll()).toBe(10); + expect(sum.current).toBe(10); stale.expect(() => (cellB.current += 2), "stale"); - expect(sum.poll()).toBe(14); + expect(sum.current).toBe(14); cellA.current += 2; stale.expect("stale"); - expect(sum.poll()).toBe(14 + 4 /* cellA increase */ + 6 /* cellC * 2 */); + expect(sum.current).toBe(14 + 4 /* cellA increase */ + 6 /* cellC * 2 */); unsubscribe(); stale.expect(() => (cellA.current += 2), "fresh"); - expect(sum.poll()).toBe(28); + expect(sum.current).toBe(28); }); }); diff --git a/packages/universal/runtime/tests/package.json b/packages/universal/runtime/tests/package.json index 619a20f7..81ede178 100644 --- a/packages/universal/runtime/tests/package.json +++ b/packages/universal/runtime/tests/package.json @@ -11,6 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/shared": "workspace:^" } diff --git a/packages/universal/runtime/tests/protocol.spec.ts b/packages/universal/runtime/tests/protocol.spec.ts index 3e4eb214..14a55c6e 100644 --- a/packages/universal/runtime/tests/protocol.spec.ts +++ b/packages/universal/runtime/tests/protocol.spec.ts @@ -1,24 +1,17 @@ -import { callerStack, Desc } from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; import type { Tagged } from "@starbeam/interfaces"; +import { Cell, Static } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; import { - CellTag, dependenciesInTaggedList, FormulaTag, getTag, lastUpdatedInTaggedList, zero, } from "@starbeam/tags"; -import { TAG, TIMELINE } from "@starbeam/runtime"; -import { beforeAll, describe, expect, it } from "vitest"; - -import { Cell, FreezableCell, Static } from "./support/mini-reactives.js"; +import { describe, expect, it } from "vitest"; describe("Tagged", () => { - beforeAll(() => { - // make sure the timeline is not at 0, which would make a comparison with TIMELINE.now sometimes - // equivalent to Timestamp.zero(), and we want to test the difference. - TIMELINE.bump(CellTag.create(Desc("cell"), zero()), callerStack(-1)); - }); describe("Static", () => { it("has the zero timestamp for lastUpdated", () => { const tom = Static("Tom Dale"); @@ -37,11 +30,11 @@ describe("Tagged", () => { describe("Cell", () => { it("has the current timestamp for lastUpdated", () => { - const original = TIMELINE.now; + const original = PUBLIC_TIMELINE.now; const tom = Cell("Tom"); - expect(String(getTag(tom).lastUpdated)).toBe(String(TIMELINE.now)); + expect(String(getTag(tom).lastUpdated)).toBe(String(PUBLIC_TIMELINE.now)); const nullvox = Cell("nullvox"); - const nullvoxTimestamp = TIMELINE.now; + const nullvoxTimestamp = PUBLIC_TIMELINE.now; expect(String(getTag(nullvox).lastUpdated), "lastUpdated(nullvox)").toBe( String(nullvoxTimestamp) @@ -49,24 +42,26 @@ describe("Tagged", () => { expect( String(lastUpdatedInTaggedList([tom, nullvox])), "lastUpdatedIn([tom,nullvox])" - ).toBe(String(TIMELINE.now)); + ).toBe(String(PUBLIC_TIMELINE.now)); - expect(String(TIMELINE.now)).not.toBe(String(original)); + expect(String(PUBLIC_TIMELINE.now)).not.toBe(String(original)); - console.log("reading", TIMELINE.now); + console.log("reading", PUBLIC_TIMELINE.now); tom.read(); - console.log("writing", TIMELINE.now); + console.log("writing", PUBLIC_TIMELINE.now); tom.current = "Tom Dale"; - console.log("wrote", TIMELINE.now); - expect(String(TIMELINE.now), "TIMELINE.now").not.toBe(String(original)); + console.log("wrote", PUBLIC_TIMELINE.now); + expect(String(PUBLIC_TIMELINE.now), "PUBLIC_TIMELINE.now").not.toBe( + String(original) + ); expect(String(getTag(tom).lastUpdated), "lastUpdated(tom)").toBe( - String(TIMELINE.now) + String(PUBLIC_TIMELINE.now) ); expect(String(getTag(nullvox).lastUpdated)).toBe( String(nullvoxTimestamp) ); expect(String(lastUpdatedInTaggedList([tom, nullvox]))).toBe( - String(TIMELINE.now) + String(PUBLIC_TIMELINE.now) ); }); @@ -82,8 +77,8 @@ describe("Tagged", () => { }); it("has no dependencies if it's frozen", () => { - const tom = FreezableCell("tom"); - const nullvox = FreezableCell("nullvox"); + const tom = Cell("tom"); + const nullvox = Cell("nullvox"); tom.freeze(); nullvox.current = "@nullvoxpopuli"; @@ -100,13 +95,18 @@ describe("Tagged", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - const formula = FormulaTag.create(Desc("formula"), () => [tom, nullvox]); + const formula = FormulaTag.create(Desc("formula"), () => [ + getTag(tom), + getTag(nullvox), + ]); const Both: Tagged = { [TAG]: formula, }; - expect(String(getTag(Both).lastUpdated)).toBe(String(TIMELINE.now)); + expect(String(getTag(Both).lastUpdated)).toBe( + String(PUBLIC_TIMELINE.now) + ); expect([...getTag(Both).dependencies()]).toEqual([ tom[TAG], @@ -115,7 +115,9 @@ describe("Tagged", () => { tom.current = "Tom Dale"; - expect(String(getTag(Both).lastUpdated)).toBe(String(TIMELINE.now)); + expect(String(getTag(Both).lastUpdated)).toBe( + String(PUBLIC_TIMELINE.now) + ); }); }); }); diff --git a/packages/universal/runtime/tests/pollable.spec.ts b/packages/universal/runtime/tests/subscribing.spec.ts similarity index 71% rename from packages/universal/runtime/tests/pollable.spec.ts rename to packages/universal/runtime/tests/subscribing.spec.ts index 0f855724..3d4507be 100644 --- a/packages/universal/runtime/tests/pollable.spec.ts +++ b/packages/universal/runtime/tests/subscribing.spec.ts @@ -1,18 +1,17 @@ import { isPresentArray } from "@starbeam/core-utils"; -import { Desc, descriptionFrom } from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; -import { DelegateTag } from "@starbeam/tags"; -import { Frame, TAG, TIMELINE } from "@starbeam/runtime"; +import { Cell, Formula } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; +import { DelegateTag, getTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; -import { Cell } from "./support/mini-reactives.js"; - -describe("pollable", () => { +describe("Tagged", () => { test("subscribing to a cell", () => { const cell = Cell(0); let stale = false; - TIMELINE.on.change(cell, () => { + PUBLIC_TIMELINE.on.change(cell, () => { stale = true; }); @@ -26,12 +25,12 @@ describe("pollable", () => { expect(cell.current).toBe(1); }); - test("subscribing to a composite", () => { + test("subscribing to a formula", () => { let stale = false; const { sum, numbers } = Sum(); - TIMELINE.on.change(sum, () => { + PUBLIC_TIMELINE.on.change(sum, () => { stale = true; }); @@ -63,12 +62,12 @@ describe("pollable", () => { const delegate: ReactiveValue = { read: () => cell.current, - [TAG]: DelegateTag.create(Desc("delegate"), [cell]), + [TAG]: DelegateTag.create(Desc("delegate"), [getTag(cell)]), }; let stale = false; - TIMELINE.on.change(delegate, () => { + PUBLIC_TIMELINE.on.change(delegate, () => { stale = true; }); @@ -87,12 +86,12 @@ describe("pollable", () => { const delegate: ReactiveValue = { read: () => sum.read(), - [TAG]: DelegateTag.create(Desc("delegate"), [sum]), + [TAG]: DelegateTag.create(Desc("delegate"), [getTag(sum)]), }; let stale = false; - const unsubscribe = TIMELINE.on.change(delegate, () => { + const unsubscribe = PUBLIC_TIMELINE.on.change(delegate, () => { stale = true; }); @@ -128,27 +127,11 @@ function Sum(): { sum: ReactiveValue; numbers: Cell[]>; } { - const numbers: Cell[]> = Cell([]); - - const frame = Frame.uninitialized( - TIMELINE.now, - descriptionFrom({ - type: "formula", - api: "Formula", - }) - ); + const numbers = Cell([] as Cell[]); - const sum: ReactiveValue = { - read: () => { - return Frame.value( - frame.evaluate( - () => numbers.current.reduce((acc, cell) => acc + cell.current, 0), - TIMELINE.frame - ) - ); - }, - [TAG]: DelegateTag.create(Desc("delegate"), [frame]), - }; + const sum = Formula(() => + numbers.current.reduce((acc, cell) => acc + cell.current, 0) + ); return { sum, numbers }; } diff --git a/packages/universal/runtime/tests/subscription.ts b/packages/universal/runtime/tests/subscription.spec.ts similarity index 50% rename from packages/universal/runtime/tests/subscription.ts rename to packages/universal/runtime/tests/subscription.spec.ts index 116abacd..e1fff728 100644 --- a/packages/universal/runtime/tests/subscription.ts +++ b/packages/universal/runtime/tests/subscription.spec.ts @@ -1,24 +1,20 @@ -import { Desc } from "@starbeam/debug"; -import { Frame, TIMELINE } from "@starbeam/runtime"; +import { Cell, Formula } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; -import { Cell } from "./support/mini-reactives.js"; - describe("frames", () => { test("subscription before first consumption", () => { const cell = Cell("Tom Dale"); - const frame = TIMELINE.frame.evaluate(() => cell.current, { - description: Desc("formula"), - }); + const formula = Formula(() => cell.current); let stale = false; - const unsubscribe = TIMELINE.on.change(frame, () => { + const unsubscribe = PUBLIC_TIMELINE.on.change(formula, () => { stale = true; }); - expect(Frame.value(frame)).toBe("Tom Dale"); + expect(formula.current).toBe("Tom Dale"); // The pollable doesn't fire initially. expect(stale).toBe(false); @@ -28,34 +24,28 @@ describe("frames", () => { expect(stale).toBe(true); stale = false; - frame.evaluate(() => cell.current, TIMELINE.frame); - - expect(Frame.value(frame)).toBe("Jerry Seinfeld"); + expect(formula.read()).toBe("Jerry Seinfeld"); unsubscribe(); cell.current = "J. Seinfeld"; - expect(stale).toBe(false); - - frame.evaluate(() => cell.current, TIMELINE.frame); + // the subscription doesn't fire after it was ubsubscribed expect(stale).toBe(false); // The lack of a subscription doesn't make the value incorrect - expect(Frame.value(frame)).toBe("J. Seinfeld"); + expect(formula.current).toBe("J. Seinfeld"); }); test("subscription after first consumption", () => { const cell = Cell("Tom Dale"); - const frame = TIMELINE.frame.evaluate(() => cell.current, { - description: Desc("formula"), - }); + const formula = Formula(() => cell.current); let stale = false; - expect(Frame.value(frame)).toBe("Tom Dale"); + expect(formula.read()).toBe("Tom Dale"); - const unsubscribe = TIMELINE.on.change(frame, () => { + const unsubscribe = PUBLIC_TIMELINE.on.change(formula, () => { stale = true; }); @@ -67,18 +57,14 @@ describe("frames", () => { expect(stale).toBe(true); stale = false; - frame.evaluate(() => cell.current, TIMELINE.frame); - expect(Frame.value(frame)).toBe("Jerry Seinfeld"); + expect(formula.current).toBe("Jerry Seinfeld"); unsubscribe(); cell.current = "J. Seinfeld"; expect(stale).toBe(false); - frame.evaluate(() => cell.current, TIMELINE.frame); - expect(stale).toBe(false); - // The lack of a subscription doesn't make the value incorrect - expect(Frame.value(frame)).toBe("J. Seinfeld"); + expect(formula.current).toBe("J. Seinfeld"); }); }); diff --git a/packages/universal/runtime/tests/support/mini-reactives.ts b/packages/universal/runtime/tests/support/mini-reactives.ts deleted file mode 100644 index 2bb5d30d..00000000 --- a/packages/universal/runtime/tests/support/mini-reactives.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { - callerStack, - Desc, - descriptionFrom, - type Stack, -} from "@starbeam/debug"; -import type { ReactiveCell, ReactiveValue, Tagged } from "@starbeam/interfaces"; -import { TAG, type UNINITIALIZED } from "@starbeam/shared"; -import { CellTag, StaticTag } from "@starbeam/tags"; -import { diff, Frame, TIMELINE } from "@starbeam/runtime"; - -export interface FreezableCell extends ReactiveCell { - freeze: () => void; -} - -export type Cell = ReactiveCell; - -class CellImpl implements ReactiveCell { - readonly [TAG]: CellTag; - #value: T; - - constructor(value: T) { - this[TAG] = CellTag.create(Desc("cell")); - this.#value = value; - } - - read(caller = callerStack()): T { - TIMELINE.didConsumeCell(this, caller); - return this.#value; - } - get current(): T { - return this.read(callerStack()); - } - set current(newValue: T) { - this.#value = newValue; - - this[TAG].lastUpdated = TIMELINE.bump(this[TAG], callerStack()); - } -} - -export function Cell(value: T): CellImpl { - return new CellImpl(value); -} - -class FreezableCellImpl implements ReactiveCell { - readonly [TAG]: CellTag; - #value: T; - constructor(value: T) { - this[TAG] = CellTag.create(Desc("cell")); - - this.#value = value; - } - - read(caller: Stack): T { - TIMELINE.didConsumeCell(this, caller); - return this.#value; - } - get current(): T { - return this.read(callerStack()); - } - set current(newValue: T) { - this.#value = newValue; - - TIMELINE.bump(this[TAG], callerStack()); - } - - freeze(): void { - this[TAG].freeze(); - } -} - -export function FreezableCell(value: T): FreezableCellImpl { - return new FreezableCellImpl(value); -} - -export function Static(value: T): ReactiveValue { - return { - [TAG]: StaticTag.create(Desc("static")), - read() { - return value; - }, - }; -} - -/** - * A simplistic Formula implementation that we're using to test the fundamentals of the TIMELINE - * API. - */ -export function Formula(computation: () => T): { - frame: Frame; - poll: () => T; -} { - const frame = Frame.uninitialized( - TIMELINE.next(), - descriptionFrom({ - type: "formula", - api: "Formula", - }) - ); - - function poll(caller = callerStack()): T { - const validation = frame.validate(); - - if (validation.status === "valid") { - TIMELINE.didConsumeFrame(frame, diff.empty(), caller); - return validation.value; - } - - const result = Frame.value(frame.evaluate(computation, TIMELINE.frame)); - TIMELINE.update(frame); - TIMELINE.didConsumeFrame(frame, diff.empty(), caller); - return result; - } - - return { frame, poll }; -} - -export function Marker(): { - instance: Tagged; - update: () => void; -} { - const tag = CellTag.create(Desc("cell")); - - return { - instance: { - [TAG]: tag, - }, - update: () => { - TIMELINE.bump(tag, callerStack()); - }, - }; -} diff --git a/packages/universal/shared/src/now.ts b/packages/universal/shared/src/now.ts index 625fa87d..4c4626e8 100644 --- a/packages/universal/shared/src/now.ts +++ b/packages/universal/shared/src/now.ts @@ -14,7 +14,7 @@ let clock = coordination.now; if (!clock) { clock = coordination.now = { - timestamp: 0, + timestamp: 1, }; } diff --git a/packages/universal/tags/index.ts b/packages/universal/tags/index.ts index 42d8ad3d..d8ba9811 100644 --- a/packages/universal/tags/index.ts +++ b/packages/universal/tags/index.ts @@ -3,6 +3,7 @@ export { dependenciesInTaggedList, describeTagged, getTag, + getTags, lastUpdatedInTaggedList, taggedDescription, } from "./src/tagged.js"; diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index 34abc778..5d81c433 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -54,7 +54,7 @@ export abstract class Tag abstract readonly lastUpdated: Timestamp; - abstract dependencies(): interfaces.List; + abstract dependencies(): readonly interfaces.CellTag[]; get description(): Description { return this.#description; @@ -100,16 +100,16 @@ export class CellTag extends Tag implements interfaces.CellTag { this.#lastUpdated = timestamp; } - override *dependencies(): interfaces.List { - if (!this.#frozen) yield this; + override dependencies(): interfaces.CellTag[] { + return this.#frozen ? [] : [this]; } - update({ runtime: timeline, stack }: UpdateOptions): void { + update({ runtime }: UpdateOptions): void { if (this.#frozen) { throw TypeError("Cannot update frozen object"); } - this.#lastUpdated = timeline.bumpCell(this, stack); + this.#lastUpdated = runtime.subscriptions.bump(this); } } @@ -122,8 +122,8 @@ export class StaticTag extends Tag implements interfaces.StaticTag { override readonly lastUpdated = NOW.now; - override *dependencies(): interfaces.List { - /** static tags have no dependencies */ + override dependencies(): readonly interfaces.CellTag[] { + return []; } } @@ -162,8 +162,8 @@ export class FormulaTag extends Tag implements interfaces.FormulaTag { return lastUpdatedTimestamp; } - override *dependencies(): interfaces.List { - yield* Tag.dependenciesInList(this.children()); + override dependencies(): interfaces.CellTag[] { + return this.children().flatMap((child) => child.dependencies()); } } @@ -196,10 +196,8 @@ export class DelegateTag extends Tag implements interfaces.DelegateTag { } } - override *dependencies(): interfaces.List { - for (const target of this.#targets) { - yield* target.dependencies(); - } + override dependencies(): readonly interfaces.CellTag[] { + return this.#targets.flatMap((target) => target.dependencies()); } override get lastUpdated(): Timestamp { diff --git a/packages/universal/tags/src/tagged.ts b/packages/universal/tags/src/tagged.ts index bc087a11..fe2d1934 100644 --- a/packages/universal/tags/src/tagged.ts +++ b/packages/universal/tags/src/tagged.ts @@ -14,6 +14,12 @@ export function getTag(tagged: Tagged): T { return tagged[TAG]; } +export function getTags( + tagged: T +): { [P in keyof T]: T[P] extends Tagged ? U : never } { + return tagged.map(getTag) as any; +} + export function describeTagged( tagged: Tagged, options?: DescriptionDescribeOptions diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 3b7f2fa1..79e37b32 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -5,10 +5,6 @@ export { CustomBuilder, } from "./src/reactive-core/custom.js"; export { Wrap } from "./src/reactive-core/delegate.js"; -export { - Formula, - FormulaValidation, -} from "./src/reactive-core/formula/formula.js"; export { Linkable } from "./src/reactive-core/formula/linkable.js"; export { PolledFormula, @@ -25,7 +21,6 @@ export { type IntoReactiveObject, type IntoResource, } from "./src/reactive-core/into.js"; -export { Marker } from "./src/reactive-core/marker.js"; export type { Blueprint, IntoReactive, @@ -53,5 +48,5 @@ export { Variants, type VariantType, } from "./src/reactive-core/variants.js"; -export { Cell, type Equality, Static } from "@starbeam/reactive"; -export { LIFETIME, TAG, TIMELINE } from "@starbeam/runtime"; +export { Cell, type Equality, Formula, Static } from "@starbeam/reactive"; +export { LIFETIME, PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; diff --git a/packages/universal/universal/src/debug-renderer.ts b/packages/universal/universal/src/debug-renderer.ts index 4aa48395..5bdfedeb 100644 --- a/packages/universal/universal/src/debug-renderer.ts +++ b/packages/universal/universal/src/debug-renderer.ts @@ -1,6 +1,6 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; -import type { Unsubscribe } from "@starbeam/runtime"; -import { TIMELINE } from "@starbeam/runtime"; +import type { Unsubscribe } from "@starbeam/interfaces"; +import { PUBLIC_TIMELINE } from "@starbeam/runtime"; import { Formula } from "./reactive-core/formula/formula.js"; @@ -27,7 +27,7 @@ export const DEBUG_RENDERER = { debug(formula.read()); let dirty = false; - return TIMELINE.on.change(formula, () => { + return PUBLIC_TIMELINE.on.change(formula, () => { if (!dirty) { dirty = true; diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/universal/src/reactive-core/delegate.ts index 1e34358f..a409d732 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/universal/src/reactive-core/delegate.ts @@ -1,7 +1,7 @@ import { callerStack, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { DelegateTag, taggedDescription } from "@starbeam/tags"; -import { TAG } from "../../../runtime"; +import { TAG } from "@starbeam/runtime"; +import { DelegateTag, getTag, taggedDescription } from "@starbeam/tags"; export function Wrap( reactive: U, @@ -11,7 +11,7 @@ export function Wrap( Object.defineProperty(value, TAG, { configurable: true, writable: true, - value: DelegateTag.create(delegateDesc(reactive, desc), [reactive]), + value: DelegateTag.create(delegateDesc(reactive, desc), [getTag(reactive)]), }); Object.defineProperty(value, "read", { diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts index 44c3297d..857c2b49 100644 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/formula.ts @@ -4,7 +4,7 @@ import { descriptionFrom, } from "@starbeam/debug"; import type { Reactive, Stack } from "@starbeam/interfaces"; -import { diff, Frame, TAG, TIMELINE } from "@starbeam/runtime"; +import { diff, Frame, TAG } from "@starbeam/runtime"; import type { UNINITIALIZED } from "@starbeam/shared"; import { DelegateTag, getTag } from "@starbeam/tags"; @@ -101,7 +101,7 @@ export function Formula( enumerable: false, configurable: true, writable: true, - value: DelegateTag.create(desc, [formula.frame]), + value: DelegateTag.create(desc, [getTag(formula.frame)]), }); Object.defineProperty(fn, Symbol.for("nodejs.util.inspect.custom"), { diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts index c296439d..ce08e202 100644 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts @@ -5,7 +5,7 @@ import { descriptionFrom, } from "@starbeam/debug"; import type { Stack } from "@starbeam/interfaces"; -import { diff, Frame, TAG, TIMELINE } from "@starbeam/runtime"; +import { diff, Frame, TAG } from "@starbeam/runtime"; import type { UNINITIALIZED } from "@starbeam/shared"; import { DelegateTag, getTag } from "@starbeam/tags"; @@ -97,7 +97,7 @@ export function PolledFormula( enumerable: false, configurable: true, writable: true, - value: DelegateTag.create(desc, [formula.frame]), + value: DelegateTag.create(desc, [getTag(formula.frame)]), }); return fn as Formula; diff --git a/packages/universal/universal/src/reactive-core/formula/setups.ts b/packages/universal/universal/src/reactive-core/formula/setups.ts index e4fde52d..2db82552 100644 --- a/packages/universal/universal/src/reactive-core/formula/setups.ts +++ b/packages/universal/universal/src/reactive-core/formula/setups.ts @@ -1,8 +1,8 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; +import { Marker } from "@starbeam/reactive"; import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; import { getID } from "@starbeam/shared"; -import { Marker } from "../marker.js"; import { Formula } from "./formula.js"; type SetupFunction = (() => void) | (() => () => void); @@ -58,9 +58,11 @@ export interface Setups { export function Setups(description: Description): Setups { const setups = new Set(); - const marker = Marker( - description.implementation(getID(), { reason: "setups changed" }) - ); + const marker = Marker({ + description: description.implementation(getID(), { + reason: "setups changed", + }), + }); const register = ( setupFn: SetupFunction, @@ -77,7 +79,7 @@ export function Setups(description: Description): Setups { }; const formula = Formula(() => { - marker.consume(); + marker.read(); for (const setup of setups) { setup(); } diff --git a/packages/universal/universal/src/reactive-core/marker.ts b/packages/universal/universal/src/reactive-core/marker.ts deleted file mode 100644 index fee101cb..00000000 --- a/packages/universal/universal/src/reactive-core/marker.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { callerStack, Desc, type Description } from "@starbeam/debug"; -import type { Stack, Tagged } from "@starbeam/interfaces"; -import type * as interfaces from "@starbeam/interfaces"; -import { TAG, TIMELINE } from "@starbeam/runtime"; -import { CellTag } from "@starbeam/tags"; - -import { RUNTIME } from "../runtime.js"; - -export class ReactiveMarker implements Tagged { - static create(tag: CellTag): ReactiveMarker { - return new ReactiveMarker(tag); - } - - readonly [TAG]: CellTag; - - private constructor(tag: CellTag) { - this[TAG] = tag; - - if (import.meta.env.DEV) { - Object.defineProperty(this, TAG, { - writable: false, - }); - } - } - - freeze(): void { - this[TAG].freeze(); - } - - consume(caller = callerStack()): void { - TIMELINE.didConsumeCell(this, caller); - } - - update(caller: Stack): void { - this[TAG].update({ runtime: RUNTIME, stack: caller }); - } -} - -export function Marker(description?: string | Description): ReactiveMarker { - return ReactiveMarker.create( - CellTag.create( - Desc("cell", description).forApi({ - package: "@starbeam/universal", - name: "Marker", - }) - ) - ); -} - -export type Marker = ReactiveMarker; diff --git a/packages/universal/universal/src/reactive-core/resource/run.ts b/packages/universal/universal/src/reactive-core/resource/run.ts index 9f6ddbbe..e7194285 100644 --- a/packages/universal/universal/src/reactive-core/resource/run.ts +++ b/packages/universal/universal/src/reactive-core/resource/run.ts @@ -1,6 +1,6 @@ import { Desc, type Description } from "@starbeam/debug"; import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { LIFETIME, type Unsubscribe } from "../../../../runtime"; +import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; import type { Handler, Resource, ResourceBlueprint } from "./resource"; import type { ResourceState } from "./state.js"; diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index ff8cd9af..25f42c7a 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -5,15 +5,13 @@ import { descriptionFrom, DisplayStruct, } from "@starbeam/debug"; -import { Cell } from "@starbeam/reactive"; +import { Cell, getRuntime, Marker } from "@starbeam/reactive"; import type { Tagged } from "@starbeam/runtime"; -import { TAG, TIMELINE } from "@starbeam/runtime"; +import { TAG } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; -import { FormulaTag } from "@starbeam/tags"; +import { FormulaTag, getTag, getTags } from "@starbeam/tags"; import { DelegateTag } from "@starbeam/tags"; -import { Marker } from "./marker.js"; - export class VariantGroups { static empty(description: Description): VariantGroups { return new VariantGroups(description); @@ -87,7 +85,7 @@ export class VariantGroups { export class VariantGroup { static group(types: string[], description: Description): VariantGroup { - return new VariantGroup(Marker(description), new Set(types)); + return new VariantGroup(Marker({ description }), new Set(types)); } readonly #marker: Marker; @@ -103,7 +101,7 @@ export class VariantGroup { } consume(): void { - this.#marker.consume(); + this.#marker.read(); } // Transition to or from another variant. If the variant is not present in this group, then this @@ -113,7 +111,7 @@ export class VariantGroup { return; } - this.#marker.update(caller); + this.#marker.mark(caller); } } @@ -130,9 +128,11 @@ export class Variant implements Tagged { }), }); - const localTypeMarker = Marker( - description.implementation("selected:local", { reason: "selected" }) - ); + const localTypeMarker = Marker({ + description: description.implementation("selected:local", { + reason: "selected", + }), + }); return new Variant( type, @@ -144,7 +144,7 @@ export class Variant implements Tagged { description.implementation("selected", { reason: `selected`, }), - [val, localTypeMarker] + getTags([val, localTypeMarker]) ) ); } @@ -156,9 +156,11 @@ export class Variant implements Tagged { ): Variant { const val = Cell(UNINITIALIZED as T | UNINITIALIZED); - const localTypeMarker = Marker( - description.implementation("selected:local", { reason: "selected" }) - ); + const localTypeMarker = Marker({ + description: description.implementation("selected:local", { + reason: "selected", + }), + }); return new Variant( type, @@ -169,7 +171,7 @@ export class Variant implements Tagged { DelegateTag.create( description.implementation("selected", { reason: "selected" }), - [val, localTypeMarker] + getTags([val, localTypeMarker]) ) ) as Variant; } @@ -191,15 +193,15 @@ export class Variant implements Tagged { } static select(variant: Variant, caller = callerStack()): void { - variant.#localTypeMarker.update(caller); + variant.#localTypeMarker.mark(caller); } static deselect(variant: Variant, caller = callerStack()): void { - variant.#localTypeMarker.update(caller); + variant.#localTypeMarker.mark(caller); } static consumeType(variant: Variant): void { - variant.#localTypeMarker.consume(); + variant.#localTypeMarker.read(); } readonly #type: string; @@ -228,7 +230,7 @@ export class Variant implements Tagged { } get type(): string { - this.#sharedTypeMarker.consume(); + this.#sharedTypeMarker.read(); return this.#type; } @@ -328,7 +330,7 @@ class VariantsImpl implements Tagged { description: Description ): VariantsImpl { const variants: Record> = {}; - const typeMarker = Marker(description.key("type")); + const typeMarker = Marker({ description: description.key("type") }); const current = Variant.selected( value.type, @@ -359,7 +361,7 @@ class VariantsImpl implements Tagged { this.#groups = VariantGroups.empty(description); this.#description = description; this.#current = current; - this[TAG] = FormulaTag.create(description, () => [this.#current]); + this[TAG] = FormulaTag.create(description, () => [getTag(this.#current)]); } // get [TAG](): FormulaTag { @@ -435,8 +437,8 @@ class VariantsImpl implements Tagged { this.#current = this.#create(type, ["selected", value]); } - this.#typeMarker.update(caller); - TIMELINE.update(this); + this.#typeMarker.mark(caller); + getRuntime().subscriptions.update(this[TAG]); } #get(type: string): Variant { diff --git a/packages/universal/universal/src/runtime.ts b/packages/universal/universal/src/runtime.ts deleted file mode 100644 index b9e58200..00000000 --- a/packages/universal/universal/src/runtime.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { callerStack } from "@starbeam/debug"; -import type { - CellTag, - Runtime as IRuntime, - Stack, - Tagged, - Timestamp, -} from "@starbeam/interfaces"; -import { defineRuntime } from "@starbeam/reactive"; -import { TIMELINE } from "../../runtime"; - -type Timeline = typeof TIMELINE; - -class Runtime implements IRuntime { - static default(): Runtime { - return new Runtime(TIMELINE); - } - - static timeline(timeline: Timeline): Runtime { - return new Runtime(timeline); - } - - readonly #timeline: Timeline; - - private constructor(timeline: Timeline) { - this.#timeline = timeline; - } - - callerStack(): Stack { - return callerStack(); - } - - didConsumeCell(cell: Tagged, caller: Stack): void { - this.#timeline.didConsumeCell(cell, caller); - } - - bumpCell(cell: CellTag, caller: Stack): Timestamp { - return this.#timeline.bump(cell, caller); - } -} - -export const RUNTIME = Runtime.default(); - -defineRuntime(RUNTIME); diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index b6f22c4a..d0dddc7d 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -1,7 +1,7 @@ import { entryPointFn } from "@starbeam/debug"; import { Static } from "@starbeam/reactive"; +import { Frame } from "@starbeam/runtime"; import { describeTagged } from "@starbeam/tags"; -import { Frame } from "../../runtime"; import { Cell, FormulaValidation, Reactive } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; diff --git a/packages/universal/universal/tests/formula.spec.ts b/packages/universal/universal/tests/formula.spec.ts index e928ff17..4baa5364 100644 --- a/packages/universal/universal/tests/formula.spec.ts +++ b/packages/universal/universal/tests/formula.spec.ts @@ -25,7 +25,7 @@ describe("A reactive formula", () => { name: name.current, location: location.current, }), - "card" + { description: "card" } ); let last = card.current; diff --git a/packages/universal/universal/tests/resource.spec.ts b/packages/universal/universal/tests/resource.spec.ts index 31cc7110..19c83446 100644 --- a/packages/universal/universal/tests/resource.spec.ts +++ b/packages/universal/universal/tests/resource.spec.ts @@ -170,7 +170,7 @@ describe("use()", () => { return Formula( () => `${next.current} (run = ${currentRun}, i = ${currentI})`, - "OuterFormula" + { description: "OuterFormula" } ); }, "Outer"); @@ -210,7 +210,7 @@ describe("use()", () => { return Formula( () => `${cell.current}, ${innerValue.current}, formula-dep: ${formulaDep.current}`, - "Outer Formula" + { description: "Outer Formula" } ); }, "Outer"); diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts index 5b173ed4..d459d4f2 100644 --- a/packages/universal/universal/tests/setup.spec.ts +++ b/packages/universal/universal/tests/setup.spec.ts @@ -1,6 +1,5 @@ import { getTag } from "@starbeam/tags"; -import { TIMELINE } from "../../runtime"; -import { Cell, Setup } from "@starbeam/universal"; +import { Cell, PUBLIC_TIMELINE, Setup } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; describe("Setup", () => { @@ -122,7 +121,7 @@ describe("Setup", () => { }; }); - let ts = TIMELINE.now; + let ts = PUBLIC_TIMELINE.now; expect(variable).toEqual({ cell: 0, diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 6dfbae4f..0b1ad2e6 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,6 +1,6 @@ +import { PUBLIC_TIMELINE, type Tagged } from "@starbeam/runtime"; import { describeTagged } from "@starbeam/tags"; -import { type Tagged } from "../../runtime"; -import { Formula, TIMELINE, Variants } from "@starbeam/universal"; +import { Formula, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; interface Bool { @@ -71,14 +71,17 @@ describe("Variants", () => { const Lifecycle = Variants>("Lifecycle"); const lifecycle = Lifecycle.idle(); - const advance = Formula(() => { - // this is testing that only a transition from idle or to idle invalidates this formula, and - // not transitions between other variants. This formula will invalidate if the variant returns - // to `idle`, since the `lifecycle.is("idle")` check will have changed from `false` to `true`. - if (lifecycle.is("idle")) { - lifecycle.choose("loading"); - } - }, "advance"); + const advance = Formula( + () => { + // this is testing that only a transition from idle or to idle invalidates this formula, and + // not transitions between other variants. This formula will invalidate if the variant returns + // to `idle`, since the `lifecycle.is("idle")` check will have changed from `false` to `true`. + if (lifecycle.is("idle")) { + lifecycle.choose("loading"); + } + }, + { description: "advance" } + ); const render = Formula((): number | Error | "idle" | "loading" => { advance(); @@ -94,13 +97,13 @@ describe("Variants", () => { } else { throw Error("unreachable"); } - }, "render"); + }, {description: "render"}); const value = Formula(() => { return lifecycle.match({ loaded: (v) => v, }); - }, "value"); + }, {description: "value"}); const advanceStable = Stability(advance); const renderStable = Stability(render); @@ -201,7 +204,7 @@ function Stability(reactive: Tagged): { } { let changed = false; - TIMELINE.on.change(reactive, (internals) => { + PUBLIC_TIMELINE.on.change(reactive, (internals) => { if (debug) { console.group(describeTagged(reactive), "invalidated by"); console.log(internals.description.describe()); diff --git a/packages/x/store/src/flat.ts b/packages/x/store/src/flat.ts index 152a2020..b58b1bf7 100644 --- a/packages/x/store/src/flat.ts +++ b/packages/x/store/src/flat.ts @@ -5,7 +5,7 @@ import type { AggregatorFor, AggregatorInstance, } from "./aggregate.js"; -import { type FilterInstance, Filter } from "./filter.js"; +import { Filter, type FilterInstance } from "./filter.js"; import type { GroupTypeFor, TableTypes, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7419d5fc..91c4d060 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -221,6 +221,7 @@ importers: '@starbeam/universal': workspace:^ '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 + '@vitest/ui': '*' purecss: 3.0.0 react: ^18.1.0 react-dom: ^18.1.0 @@ -237,6 +238,7 @@ importers: devDependencies: '@types/react': 18.0.26 '@types/react-dom': 18.0.10 + '@vitest/ui': 0.29.7 vite: 4.2.1 vite-plugin-fonts: 0.7.0_vite@4.2.1 @@ -726,6 +728,7 @@ importers: '@starbeam-dev/build-support': workspace:* '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/runtime': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/tags': workspace:^ @@ -734,6 +737,7 @@ importers: dependencies: '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces + '@starbeam/reactive': link:../reactive '@starbeam/runtime': link:../runtime '@starbeam/shared': link:../shared '@starbeam/tags': link:../tags @@ -788,12 +792,27 @@ importers: devDependencies: '@starbeam-dev/build-support': link:../../../workspace/build + packages/universal/reactive/tests: + specifiers: + '@starbeam/debug': workspace:^ + '@starbeam/interfaces': workspace:^ + '@starbeam/reactive': workspace:^ + '@starbeam/runtime': workspace:^ + '@starbeam/shared': workspace:^ + dependencies: + '@starbeam/debug': link:../../debug + '@starbeam/interfaces': link:../../interfaces + '@starbeam/reactive': link:.. + '@starbeam/runtime': link:../../runtime + '@starbeam/shared': link:../../shared + packages/universal/runtime: specifiers: '@starbeam-dev/build-support': workspace:* '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/shared': workspace:^ '@starbeam/tags': workspace:^ '@starbeam/verify': workspace:^ @@ -801,6 +820,7 @@ importers: '@starbeam/core-utils': link:../core-utils '@starbeam/debug': link:../debug '@starbeam/interfaces': link:../interfaces + '@starbeam/reactive': link:../reactive '@starbeam/shared': link:../shared '@starbeam/tags': link:../tags '@starbeam/verify': link:../verify @@ -811,11 +831,13 @@ importers: specifiers: '@starbeam/debug': workspace:^ '@starbeam/interfaces': workspace:^ + '@starbeam/reactive': workspace:^ '@starbeam/runtime': workspace:^ '@starbeam/shared': workspace:^ dependencies: '@starbeam/debug': link:../../debug '@starbeam/interfaces': link:../../interfaces + '@starbeam/reactive': link:../../reactive '@starbeam/runtime': link:.. '@starbeam/shared': link:../../shared From 7097a554524d229a5ef9a22e2aedf42a72e83130 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 27 Mar 2023 16:48:32 -0700 Subject: [PATCH 12/46] More conceptual cleanup plus foundational docs --- @types/ansicolor/index.d.ts | 2 +- packages/preact/preact/package.json | 2 + packages/preact/preact/src/frame.ts | 12 +- .../react/react/tests/use-resource.spec.ts | 22 +-- packages/universal/core-utils/src/object.ts | 2 +- .../universal/debug/src/description/impl.ts | 54 ++++- packages/universal/interfaces/index.d.ts | 2 + .../universal/interfaces/src/description.d.ts | 2 + .../universal/interfaces/src/protocol.d.ts | 24 ++- .../universal/interfaces/src/runtime.d.ts | 4 +- packages/universal/js/src/map.ts | 130 ++++++++---- packages/universal/js/tests/weak-map.spec.ts | 25 +++ packages/universal/reactive/README.md | 66 +++++++ packages/universal/reactive/index.ts | 2 + .../universal/reactive/src/primitives/base.ts | 19 ++ .../reactive/src/primitives/cached.ts | 96 +++++++++ .../universal/reactive/src/primitives/cell.ts | 26 ++- .../src/primitives/formula-lifecycle.ts | 77 ++++++++ .../reactive/src/primitives/formula.ts | 127 ++++-------- .../reactive/src/primitives/marker.ts | 24 +-- .../reactive/src/primitives/shared.ts | 5 - .../reactive/src/primitives/static.ts | 2 +- .../reactive/src/primitives/utils.ts | 59 ++++++ packages/universal/reactive/src/runtime.ts | 40 +++- packages/universal/runtime/index.ts | 1 + .../universal/runtime/src/timeline/tracker.ts | 14 ++ .../universal/runtime/tests/consume.spec.ts | 41 ++-- .../runtime/tests/subscribing.spec.ts | 56 ++++-- .../runtime/tests/subscription.spec.ts | 37 +--- packages/universal/tags/README.md | 185 ++++++++++++++++++ packages/universal/tags/index.ts | 10 +- packages/universal/tags/src/tag.ts | 33 +++- packages/universal/universal/index.ts | 13 +- .../universal/universal/src/debug-renderer.ts | 3 +- .../src/reactive-core/formula/formula.ts | 117 ----------- .../reactive-core/formula/polled-formula.ts | 104 ---------- .../src/reactive-core/formula/setups.ts | 3 +- .../higher-level/resource-list.ts | 4 +- .../src/reactive-core/resource/resource.ts | 5 +- .../src/reactive-core/resource/state.ts | 9 +- .../universal/tests/variants.spec.ts | 55 +++--- pnpm-lock.yaml | 4 + 42 files changed, 1003 insertions(+), 515 deletions(-) create mode 100644 packages/universal/reactive/README.md create mode 100644 packages/universal/reactive/src/primitives/base.ts create mode 100644 packages/universal/reactive/src/primitives/cached.ts create mode 100644 packages/universal/reactive/src/primitives/formula-lifecycle.ts delete mode 100644 packages/universal/reactive/src/primitives/shared.ts create mode 100644 packages/universal/reactive/src/primitives/utils.ts create mode 100644 packages/universal/tags/README.md delete mode 100644 packages/universal/universal/src/reactive-core/formula/formula.ts delete mode 100644 packages/universal/universal/src/reactive-core/formula/polled-formula.ts diff --git a/@types/ansicolor/index.d.ts b/@types/ansicolor/index.d.ts index b2fe0a25..a6eb6d8d 100644 --- a/@types/ansicolor/index.d.ts +++ b/@types/ansicolor/index.d.ts @@ -38,7 +38,7 @@ type FgColor = Expand<{ default: Color; }>; -type Color = BgColor & FgColor & ((text: string) => string); +export type Color = BgColor & FgColor & ((text: string) => string); const DEFAULT: Color; export default DEFAULT; diff --git a/packages/preact/preact/package.json b/packages/preact/preact/package.json index 827710dc..3056657c 100644 --- a/packages/preact/preact/package.json +++ b/packages/preact/preact/package.json @@ -33,9 +33,11 @@ "dependencies": { "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", "@starbeam/preact-utils": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/runtime": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index 71e0ba6b..5c26bdba 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -1,16 +1,19 @@ import { getLast } from "@starbeam/core-utils"; import type { Description } from "@starbeam/debug"; +import type { Tag } from "@starbeam/interfaces"; import type { InternalComponent } from "@starbeam/preact-utils"; import { - type ActiveFrame, type Frame, PUBLIC_TIMELINE, + RUNTIME, type Unsubscribe, } from "@starbeam/runtime"; import { expected, isPresent, verify } from "@starbeam/verify"; +type ActiveFrame = (() => Set) | null; + export class ComponentFrame { - #active: ActiveFrame | null; + #active: ActiveFrame; #frame: Frame | null; #subscription: Unsubscribe | null; @@ -69,7 +72,7 @@ export class ComponentFrame { private constructor( frame: Frame | null, - active: ActiveFrame | null, + active: ActiveFrame, subscribed: Unsubscribe | null ) { this.#frame = frame; @@ -79,7 +82,8 @@ export class ComponentFrame { #start(description: Description): void { if (this.#frame) { - this.#active = TIMELINE.frame.update(this.#frame); + this.#active = RUNTIME.autotracking.start(); + // this.#active = TIMELINE.frame.update(this.#frame); } else { this.#active = TIMELINE.frame.open({ description, diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index 676656ea..8e8e321f 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -231,17 +231,16 @@ describe("use", () => { .render( (state) => { const { name, increment } = useSetup(() => { - const count = Cell(0, `count`); + const count = Cell(0, { description: `count` }); - const name = Formula( - () => `channel${count.current}`, - `channel-name` - ); + const name = Formula(() => `channel${count.current}`, { + description: `channel-name`, + }); return { name, increment: () => { - return count.update((i) => i + 1); + count.update((i) => i + 1); }, }; }); @@ -313,19 +312,18 @@ describe("use", () => { .render( (state) => { const { channel, increment } = useSetup(({ use }) => { - const count = Cell(0, `count`); + const count = Cell(0, { description: `count` }); - const name = Formula( - () => `channel${count.current}`, - `channel-name` - ); + const name = Formula(() => `channel${count.current}`, { + description: `channel-name`, + }); const channel = use(() => SimpleChannel(name.current)); return { channel, increment: () => { - return count.update((i) => i + 1); + count.update((i) => i + 1); }, }; }); diff --git a/packages/universal/core-utils/src/object.ts b/packages/universal/core-utils/src/object.ts index ba782a8e..8042c739 100644 --- a/packages/universal/core-utils/src/object.ts +++ b/packages/universal/core-utils/src/object.ts @@ -10,7 +10,7 @@ export function objectHasKeys(object: object): boolean { return isPresentArray(Object.keys(object)); } -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; + type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; type WithReadonly = Expand< Exclude & { diff --git a/packages/universal/debug/src/description/impl.ts b/packages/universal/debug/src/description/impl.ts index 42d2b33d..dc3f45f1 100644 --- a/packages/universal/debug/src/description/impl.ts +++ b/packages/universal/debug/src/description/impl.ts @@ -1,7 +1,7 @@ import type * as interfaces from "@starbeam/interfaces"; import { getID } from "@starbeam/shared"; import { exhaustive, expected, isEqual, verify } from "@starbeam/verify"; -import ansicolor from "ansicolor"; +import ansicolor, { type Color } from "ansicolor"; import { DisplayStruct } from "../inspect/display-struct.js"; import { DisplayParts } from "../module.js"; @@ -29,6 +29,10 @@ export interface DescriptionStatics { } if (import.meta.env.DEV) { + function stylize(color: Color, text: string, shouldColor: boolean): string { + return shouldColor ? color(text) : text; + } + class DebugDescription implements interfaces.Description, interfaces.DescriptionArgs { @@ -130,7 +134,7 @@ if (import.meta.env.DEV) { return this.#stack?.caller; } - get fromUser(): string { + #fromUser(shouldColor: boolean): string { if (this.#details) { if (typeof this.#details === "string") { return this.#details; @@ -148,11 +152,15 @@ if (import.meta.env.DEV) { } case "detail": { - const detail = ansicolor.dim(`->${this.#details.name}`); + const detail = stylize( + ansicolor.dim, + `->${this.#details.name}`, + shouldColor + ); if (this.#details.args) { return `${detail}(${this.#details.args - .map((a) => ansicolor.magenta(a)) + .map((a) => stylize(ansicolor.magenta, a, shouldColor)) .join(", ")})`; } else { return detail; @@ -171,18 +179,40 @@ if (import.meta.env.DEV) { } } - get fullName(): string { + get fromUser(): string { + return this.#fromUser(true); + } + + get name(): string { if (this.#details !== undefined) { if (typeof this.#details === "string") { return this.#details; } else { - return `${this.#details.parent.fullName}${this.fromUser}`; + return this.#fromUser(false); } } else { return `{${this.#idName}:anonymous ${this.type}}`; } } + #fullName(shouldColor: boolean): string { + if (this.#details !== undefined) { + if (typeof this.#details === "string") { + return this.#details; + } else { + return `${this.#details.parent.#fullName( + shouldColor + )}${this.#fromUser(shouldColor)}`; + } + } else { + return `{${this.#idName}:anonymous ${this.type}}`; + } + } + + get fullName(): string { + return this.#fullName(false); + } + get id(): interfaces.ReactiveId { return this.#id; } @@ -281,11 +311,14 @@ if (import.meta.env.DEV) { describe(options: interfaces.DescriptionDescribeOptions = {}): string { const name = this.#name(options); + const color = options.color ?? true; if (this.#internal) { - const desc = this.#internal.reason - ? ansicolor.dim(`[${this.#internal.reason}]`) - : ansicolor.dim("[internals]"); + const desc = stylize( + ansicolor.dim, + this.#internal.reason ? `[${this.#internal.reason}]` : "[internals]", + color + ); return `${name} ${desc}`; } else { return name; @@ -445,9 +478,10 @@ if (import.meta.env.DEV) { } #name(options: interfaces.DescriptionDescribeOptions): string { + const color = options.color ?? true; const getName = (): string => { if ((this.isAnonymous || options.source) ?? false) { - return `${this.fullName} @ ${this.#caller(options)}`; + return `${this.#fullName(color)} @ ${this.#caller(options)}`; } else { return this.fullName; } diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 176eea22..a32fe068 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -42,10 +42,12 @@ export type { StaticTag, Tag, Tagged, + TaggedReactive, TagMethods, TagType, } from "./src/protocol.js"; export type { + ActiveFrame, AutotrackingRuntime, DeprecatedTimeline, Runtime, diff --git a/packages/universal/interfaces/src/description.d.ts b/packages/universal/interfaces/src/description.d.ts index 75404cdf..4da57de9 100644 --- a/packages/universal/interfaces/src/description.d.ts +++ b/packages/universal/interfaces/src/description.d.ts @@ -42,9 +42,11 @@ export interface DescriptionArgs { export interface DescriptionDescribeOptions extends StackFrameDisplayOptions { source?: boolean | undefined; id?: boolean | undefined; + color?: boolean | undefined; } export interface Description extends DescriptionArgs { + readonly name: string; readonly fullName: string; readonly id: ReactiveId; readonly type: DescriptionType; diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index b7ff7cbe..09d4a64d 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -1,6 +1,7 @@ import type { TAG } from "@starbeam/shared"; import type { Description } from "./description.js"; +import type { UpdateOptions } from "./runtime.js"; import type { Stack } from "./stack.js"; import type { Timestamp } from "./timestamp.js"; @@ -9,6 +10,13 @@ export type ReactiveId = number | string | ReactiveId[]; export interface AbstractTag { readonly type: TagType; readonly description: Description; + + /** + * This flag is false in formula tags, when the tag hasn't been computed yet. + * This avoids subscribing to a formula without computing its value, which is + * a violation of the tag contract. + */ + readonly tdz: boolean; } export type List = Iterable | T[] | readonly T[]; @@ -39,7 +47,7 @@ export type Matcher = ExhaustiveMatcher | DefaultMatcher; export interface CellTag extends AbstractTag, TagMethods { readonly type: "cell"; readonly lastUpdated: Timestamp; - isFrozen?: () => boolean; + isFrozen: () => boolean; freeze: () => void; update: (options: UpdateOptions) => void; } @@ -58,6 +66,15 @@ export interface CellTag extends AbstractTag, TagMethods { */ export interface FormulaTag extends AbstractTag, TagMethods { readonly type: "formula"; + /** + * The current children of this formula. Note that "no children" does not + * necessarily mean that the formula is static, because a formula has no + * children before it was first initialized. + * + * Data structures built on `FormulaTag` should always read the formula before + * attempting to read the children if they plan to rely on the absence of + * children as a strong indicator of staticness. + */ children: () => readonly Tag[]; } @@ -132,6 +149,11 @@ export interface Reactive extends ReactiveValue { readonly current: T; } +export interface TaggedReactive + extends ReactiveValue { + readonly current: T; +} + export interface ReactiveCell extends Reactive { current: T; } diff --git a/packages/universal/interfaces/src/runtime.d.ts b/packages/universal/interfaces/src/runtime.d.ts index 4356cadc..7c1942bb 100644 --- a/packages/universal/interfaces/src/runtime.d.ts +++ b/packages/universal/interfaces/src/runtime.d.ts @@ -25,8 +25,10 @@ export interface SubscriptionRuntime { update: (formula: FormulaTag) => void; } +export type ActiveFrame = () => Set; + export interface AutotrackingRuntime { - start: () => () => Set; + start: () => ActiveFrame; consume: (tag: Tag) => void; } diff --git a/packages/universal/js/src/map.ts b/packages/universal/js/src/map.ts index eca46a60..848f5bfe 100644 --- a/packages/universal/js/src/map.ts +++ b/packages/universal/js/src/map.ts @@ -1,7 +1,11 @@ +import type { Stack } from "@starbeam/debug"; import { callerStack, type Description } from "@starbeam/debug"; -import type { Equality } from "@starbeam/universal"; +import { type Equality, Marker } from "@starbeam/reactive"; -import { Collection } from "./collection.js"; +interface Entry { + has: Marker; + get: Marker; +} export class TrackedWeakMap implements WeakMap @@ -12,73 +16,111 @@ export class TrackedWeakMap return new TrackedWeakMap(description) as WeakMap; } - readonly #collection: Collection; + readonly #description: Description; + readonly #iteration: Marker; + readonly #storage: WeakMap; readonly #vals: WeakMap; readonly #equals: Equality = Object.is; private constructor(description: Description) { - // TypeScript doesn't correctly resolve the overloads for calling the `Map` - // constructor for the no-value constructor. This resolves that. this.#vals = new WeakMap(); - // FIXME: Avoid using a regular Map in Collection to avoid leaks. The best - // thing to do would probably be to have a non-iterable, object-keyed - // Collection that WeakMap and WeakSet can use. - this.#collection = Collection.create(description, this); + this.#iteration = Marker(description.detail("iterate")); + this.#storage = new WeakMap(); + + this.#description = description; } - get(key: K): V | undefined { - const has = this.#vals.has(key); + #entry(key: K): Entry { + let markers = this.#tryEntry(key); - this.#collection.get(key, has ? "hit" : "miss", " {entry}", callerStack()); + if (markers === undefined) { + markers = { + get: Marker(this.#description.key(describeKey(key)).detail("get")), + has: Marker(this.#description.key(describeKey(key)).detail("has")), + }; + this.#storage.set(key, markers); + } + + return markers; + } + + #tryEntry(key: K): Entry | undefined { + return this.#storage.get(key); + } + + #get(key: K, caller: Stack, entry: Entry = this.#entry(key)): V | undefined { + entry.get.read(caller); return this.#vals.get(key); } + get(key: K): V | undefined { + const caller = callerStack(); + const entry = this.#entry(key); + return this.#has(key, caller, entry) + ? this.#get(key, caller, entry) + : undefined; + } + + #has(key: K, caller: Stack, entry: Entry = this.#entry(key)): boolean { + entry.has.read(caller); + return this.#vals.has(key); + } + has(key: K): boolean { - const has = this.#vals.has(key); - this.#collection.check( - key, - has ? "hit" : "miss", - " {entry}", - callerStack() - ); - return has; + return this.#has(key, callerStack()); + } + + #insert(key: K, caller: Stack): void { + const entry = this.#tryEntry(key); + if (entry) entry.has.mark(caller); + + this.#iteration.mark(caller); + } + + #update(key: K, caller: Stack): void { + const entry = this.#tryEntry(key); + if (entry) entry.get.mark(caller); + + this.#iteration.mark(caller); } set(key: K, value: V): this { const caller = callerStack(); + // intentionally avoid consuming the `has` or `get` markers while setting. const has = this.#vals.has(key); if (has) { const current = this.#vals.get(key) as V; - - if (this.#equals(current, value)) { - return this; - } + if (!this.#equals(current, value)) this.#update(key, caller); + } else { + this.#insert(key, caller); } - this.#collection.set( - key, - has ? "key:stable" : "key:changes", - " {entry}", - caller - ); this.#vals.set(key, value); return this; } + #delete(key: K, caller: Stack): void { + const entry = this.#tryEntry(key); + + // if anyone checked the presence of this key before, invalidate the check. + if (entry) entry.has.mark(caller); + + // either way, invalidate iteration of the map. + this.#iteration.mark(caller); + } + delete(key: K): boolean { const caller = callerStack(); - const has = this.#vals.has(key); - - if (!has) { - return false; + // if the key is not in the map, then deleting it has no reactive effect. + if (this.#vals.has(key)) { + this.#delete(key, caller); } - this.#collection.delete(key, caller); return this.#vals.delete(key); } @@ -89,3 +131,21 @@ export class TrackedWeakMap // So instanceof works Object.setPrototypeOf(TrackedWeakMap.prototype, WeakMap.prototype); + +function describeKey(key: unknown): string { + switch (typeof key) { + case "object": + return key === null ? "null" : "{key} "; + case "function": + return "{function} "; + case "undefined": + case "bigint": + case "symbol": + case "string": + case "number": + case "boolean": + return String(key); + default: + throw Error(`UNEXPECTED: typeof value=${typeof key}`); + } +} diff --git a/packages/universal/js/tests/weak-map.spec.ts b/packages/universal/js/tests/weak-map.spec.ts index 8f7f6081..8c21c631 100644 --- a/packages/universal/js/tests/weak-map.spec.ts +++ b/packages/universal/js/tests/weak-map.spec.ts @@ -1,4 +1,5 @@ import { reactive } from "@starbeam/js"; +import { CachedFormula } from "@starbeam/reactive"; import { describe, expect, test } from "vitest"; import { Invalidation } from "./support.js"; @@ -10,6 +11,30 @@ describe("TrackedWeakMap", () => { const hamburgers = { name: "hamburgers" }; const smashburgers = { name: "smashburgers" }; + test("basics", () => { + const map = reactive.WeakMap(); + const delicious = CachedFormula(() => { + return map.has(brie) || map.has(chevre); + }); + + expect(delicious.current).toEqual(false); + + map.set(hotDogs, "sandwich"); + expect(delicious.current).toEqual(false); + + map.set(brie, "cheese"); + expect(delicious.current).toEqual(true); + + map.set(chevre, "cheese"); + expect(delicious.current).toEqual(true); + + map.delete(brie); + expect(delicious.current).toEqual(true); + + map.delete(chevre); + expect(delicious.current).toEqual(false); + }); + test("checking a non-existent item invalidates if the item is added", () => { const map = reactive.WeakMap(); diff --git a/packages/universal/reactive/README.md b/packages/universal/reactive/README.md new file mode 100644 index 00000000..d87899ef --- /dev/null +++ b/packages/universal/reactive/README.md @@ -0,0 +1,66 @@ +This package contains the implementations of the reactive primitives. + +Reactive primitives must be used with an implementation of `Runtime`, which +basically means that they must be used together with `@reactive/runtime`. + +> The primitives themselves, and higher-level concepts built on the primitives are +> agnostic to the runtime, primarily to clearly mark the runtime interface and +> allow us to revise its implementation over time cleanly. +> +> It is not possible to use multiple runtimes at the same time, and the runtime +> interface is not exposed to the user. + +This package provides primitive reactive _values_, building on `@starbeam/tags`, +which provides primitive _tags_ (composable validation). + +## The Reactive Protocol + +All primitive reactive values implement the reactive protocol: + +- `read()`: read the current value of the reactive +- `[TAG]`: get the tag for the reactive value. Tags are stable for the lifetime + of the reactive value, and therefore may be used to identify the value and cached. + +## The Primitives + +### Cell + +A cell represents storage for a single atomic value. + +A cell has an "equivalence" property: when the cell is updated with a value that is +equivalent to the previous value, the new value is ignored. The default +equivalent property is `Object.is`, but it can be overridden with the `equals` +option to the `Cell()` constructor . + +In addition to `read()`, a cell also has these fundamental operations: + +- `update(T => T)`: update the value of the cell. This method takes a callback + that receives the previous value and returns a new value. This method does not + consume the cell. +- `freeze()`: freeze the value of the cell. The cell can no longer be updated, + so any subscribers to the cell are automatically unsubscribed. + +`Cell` also has a few conveniences: + +- The `current` property, which is mutable. This makes it possible to write + things like `cell.current++`. +- the `set` method, which just takes a new value and updates the cell. + +### Marker + +A marker is a simple primitive that has no value, but instead represents values +stored elsewhere. For example, reactive collections store their values in the +JavaScript collections they represent, and use markers to represent each +discrete piece of storage in the collection. + +A marker has these fundamental operations: + +- `mark()`: mark the external storage as being dirty. +- `read()`: add the external storage to the current tracking frame. +- `freeze()`: indicate the the external storage will never change in the future. + +> Reactive collections use markers more interestingly than just to represent +> external values. For example, reactive `Map` has a marker for both `has` and +> `get` for each entry in the map. This means that if a formula used a `has` +> check to check for a key's presence and it returns `true`, updating the value +> of that key will not invalidate the formula. diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 30a4e458..a020d1ff 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -1,6 +1,8 @@ +export { CachedFormula } from "./src/primitives/cached.js"; export type { CellOptions, Equality } from "./src/primitives/cell.js"; export { Cell } from "./src/primitives/cell.js"; export { Formula } from "./src/primitives/formula.js"; +export { FormulaLifecycle } from "./src/primitives/formula-lifecycle.js"; export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; export { defineRuntime, getRuntime } from "./src/runtime.js"; diff --git a/packages/universal/reactive/src/primitives/base.ts b/packages/universal/reactive/src/primitives/base.ts new file mode 100644 index 00000000..c9f5b297 --- /dev/null +++ b/packages/universal/reactive/src/primitives/base.ts @@ -0,0 +1,19 @@ +import { readonly } from "@starbeam/core-utils"; +import type { Stack, Tag } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; + +import { getRuntime } from "../runtime.js"; + +export abstract class ReactivePrimitive { + declare readonly [TAG]: T; + + constructor(tag: T) { + readonly(this, TAG, tag); + } + + abstract read(caller: Stack): V; + + get current(): V { + return this.read(getRuntime().callerStack()); + } +} diff --git a/packages/universal/reactive/src/primitives/cached.ts b/packages/universal/reactive/src/primitives/cached.ts new file mode 100644 index 00000000..d1d896de --- /dev/null +++ b/packages/universal/reactive/src/primitives/cached.ts @@ -0,0 +1,96 @@ +import { callerStack, Desc, type Description } from "@starbeam/debug"; +import type { ReactiveFormula } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { FormulaTag } from "@starbeam/tags"; + +import { RUNTIME } from "../runtime.js"; +import type { Formula } from "./formula.js"; +import { + type FinalizedFormula, + FormulaLifecycle, +} from "./formula-lifecycle.js"; +import { + type FormulaFn, + type SugaryPrimitiveOptions, + toOptions, + WrapFn, +} from "./utils.js"; + +interface Last { + readonly formula: FinalizedFormula; + value: T; +} + +class FormulaImpl implements ReactiveFormula { + static create = ( + compute: () => T, + options?: SugaryPrimitiveOptions + ): FormulaFn => { + const { description } = toOptions(options); + const formula = new FormulaImpl(compute, Desc("formula", description)); + + return WrapFn(formula); + }; + + declare readonly [TAG]: FormulaTag; + readonly #compute: () => T; + #last: Last | null; + + private constructor(compute: () => T, description: Description) { + this.#last = null; + this.#compute = compute; + this[TAG] = FormulaTag.create(description, () => { + if (this.#last === null) return []; + return this.#last.formula[TAG].children(); + }); + } + + get current(): T { + return this.read(callerStack()); + } + + read(_caller = callerStack()): T { + const value = this.#evaluate(); + RUNTIME.autotracking.consume(this[TAG]); + return value; + } + + #evaluate(): T { + if (this.#last === null) { + return this.#initialize(); + } else if (this.#last.formula.isStale()) { + return this.#update(this.#last); + } else { + return this.#last.value; + } + } + + #initialize(): T { + const lifecycle = FormulaLifecycle(this[TAG].description); + const value = this.#compute(); + const formula = lifecycle.done(); + + this.#last = { + formula, + value, + }; + + // Allow the formula to be subscribed to. + this[TAG].unsetTdz(); + + return value; + } + + #update(last: Last): T { + const lifecycle = last.formula.update(); + const value = this.#compute(); + lifecycle.done(); + RUNTIME.subscriptions.update(this[TAG]); + + last.value = value; + return value; + } +} + +export const CachedFormula = FormulaImpl.create; +export type CachedFormula = Formula; diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index 60df6e66..8a1b6feb 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -1,18 +1,27 @@ import { readonly } from "@starbeam/core-utils"; import type * as Debug from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; -import type { CellTag as ICellTag, ReactiveCell } from "@starbeam/interfaces"; +import type { + CellTag as ICellTag, + Expand, + ReactiveCell, +} from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { CellTag } from "@starbeam/tags"; import { getRuntime } from "../runtime.js"; -import type { PrimitiveOptions } from "./shared.js"; +import { + type DescriptionOption, + isDescriptionOption, + type PrimitiveOptions, +} from "./utils.js"; export class CellImpl implements ReactiveCell { static create = ( value: T, - { description, equals = Object.is }: CellOptions = {} + options?: CellOptions | DescriptionOption ): CellImpl => { + const { description, equals = Object.is } = toCellOptions(options); return new CellImpl(value, equals, Desc("cell", description)); }; @@ -39,7 +48,6 @@ export class CellImpl implements ReactiveCell { } read(_caller = getRuntime().callerStack()): T { - // getRuntime().timeline.didConsumeCell(this[TAG], caller); getRuntime().autotracking.consume(this[TAG]); return this.#value; } @@ -50,7 +58,7 @@ export class CellImpl implements ReactiveCell { } this.#value = value; - this[TAG].update({ stack: caller, runtime: getRuntime() }); + this[TAG].update({ caller, runtime: getRuntime() }); } update(updater: (prev: T) => T, caller = getRuntime().callerStack()) { @@ -63,10 +71,16 @@ export class CellImpl implements ReactiveCell { } export const Cell = CellImpl.create; -export type Cell = CellImpl; +export type Cell = Expand>; export type Equality = (a: T, b: T) => boolean; export interface CellOptions extends PrimitiveOptions { equals?: Equality; } + +export function toCellOptions( + options: CellOptions | DescriptionOption +): CellOptions { + return isDescriptionOption(options) ? { description: options } : options; +} diff --git a/packages/universal/reactive/src/primitives/formula-lifecycle.ts b/packages/universal/reactive/src/primitives/formula-lifecycle.ts new file mode 100644 index 00000000..8a4c556b --- /dev/null +++ b/packages/universal/reactive/src/primitives/formula-lifecycle.ts @@ -0,0 +1,77 @@ +import { Desc } from "@starbeam/debug"; +import type { + ActiveFrame, + Description, + Expand, + Tagged, + Timestamp, +} from "@starbeam/interfaces"; +import type { Tag } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import { FormulaTag, NOW } from "@starbeam/tags"; + +import { getRuntime } from "../runtime.js"; +import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; + +export class InitializingFormulaImpl { + static start = (options?: SugaryPrimitiveOptions): InitializingFormula => { + const { description } = toOptions(options); + const active = getRuntime().autotracking.start(); + return new InitializingFormulaImpl(active, Desc("formula", description)); + }; + + readonly #active: ActiveFrame; + readonly #description: Description; + + private constructor(active: () => Set, description: Description) { + this.#active = active; + this.#description = description; + } + + done(): FinalizedFormula { + return new FinalizedFormulaImpl(this.#active(), NOW.now, this.#description); + } +} + +export const FormulaLifecycle = InitializingFormulaImpl.start; +export type InitializingFormula = Expand; +export type FinalizedFormula = Expand; + +class FinalizedFormulaImpl implements Tagged { + static create = ( + children: Set, + description: Description + ): FinalizedFormula => { + return new FinalizedFormulaImpl(children, NOW.now, description); + }; + + #children: Set; + #lastValidated: Timestamp; + declare readonly [TAG]: FormulaTag; + + constructor( + children: Set, + lastValidated: Timestamp, + description: Description + ) { + this.#children = children; + this.#lastValidated = lastValidated; + this[TAG] = FormulaTag.create(description, () => this.#children); + } + + isStale(): boolean { + return this[TAG].lastUpdated.gt(this.#lastValidated); + } + + update(): { done: () => void } { + const done = getRuntime().autotracking.start(); + + return { + done: () => { + this.#children = done(); + this.#lastValidated = NOW.now; + getRuntime().subscriptions.update(this[TAG]); + }, + }; + } +} diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts index 0ed85fd6..c7f079a4 100644 --- a/packages/universal/reactive/src/primitives/formula.ts +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -1,113 +1,54 @@ -import { readonly } from "@starbeam/core-utils"; -import { Desc, type Description } from "@starbeam/debug"; +import { Desc } from "@starbeam/debug"; import type { - Reactive, + Description, + Expand, ReactiveFormula, - Stack, - Tag as ITag, + Tag, } from "@starbeam/interfaces"; -import { TAG, UNINITIALIZED } from "@starbeam/shared"; -import { Tag, type Timestamp, zero } from "@starbeam/tags"; -import { FormulaTag, NOW } from "@starbeam/tags"; - -import { getRuntime } from "../runtime.js"; -import type { PrimitiveOptions } from "./shared.js"; - -interface FormulaFn extends Reactive { - (): T; -} - -class FormulaImpl implements ReactiveFormula { - static create = ( - compute: () => T, - { description }: PrimitiveOptions = {} - ): FormulaFn => { +import { TAG } from "@starbeam/shared"; +import { FormulaTag } from "@starbeam/tags"; + +import { RUNTIME } from "../runtime.js"; +import { ReactivePrimitive } from "./base.js"; +import { + type FormulaFn, + type SugaryPrimitiveOptions, + toOptions, + WrapFn, +} from "./utils.js"; + +export class FormulaImpl + extends ReactivePrimitive + implements ReactiveFormula +{ + static create = (compute: () => T, options?: SugaryPrimitiveOptions) => { + const { description } = toOptions(options); const formula = new FormulaImpl(compute, Desc("formula", description)); - const fn = (): T => { - return formula.read(getRuntime().callerStack()); - }; - - Object.defineProperties(fn, { - current: { - get: fn, - }, - [TAG]: { - get: () => formula[TAG], - }, - read: { - value: fn, - }, - }); - - return fn as FormulaFn; + return WrapFn(formula); }; - declare readonly [TAG]: FormulaTag; - readonly #memo: Memo; - #children = new Set(); - #lastValidated: Timestamp = zero(); + #compute: () => T; + #children = new Set(); private constructor(compute: () => T, description: Description) { - this.#memo = new Memo(compute); - readonly( - this, - TAG, - FormulaTag.create(description, () => this.#children) - ); - } - - get current(): T { - return this.read(getRuntime().callerStack()); - } - - read(_stack?: Stack | undefined): T { - const value = this.#value(); - getRuntime().autotracking.consume(this[TAG]); - return value; + super(FormulaTag.create(description, () => this.#children)); + this.#compute = compute; } - #value(): T { - const last = this.#memo.last; + read(_caller = RUNTIME.callerStack()): T { + const { value, tags } = RUNTIME.evaluate(this.#compute); + this.#children = tags; - if (last === UNINITIALIZED || this.#isStale()) { - return this.#evaluate(); + if (this[TAG].tdz) { + this[TAG].unsetTdz(); } else { - return last; + RUNTIME.subscriptions.update(this[TAG]); } - } - #evaluate(): T { - const done = getRuntime().autotracking.start(); - const value = this.#memo.compute(); - this.#children = done(); - this.#lastValidated = NOW.now; - getRuntime().subscriptions.update(this[TAG]); return value; } - - #isStale(): boolean { - return Tag.lastUpdatedIn(this.#children).gt(this.#lastValidated); - } -} - -class Memo { - #value: T | UNINITIALIZED = UNINITIALIZED; - readonly #compute: () => T; - - constructor(compute: () => T) { - this.#compute = compute; - } - - compute(): T { - this.#value = this.#compute(); - return this.#value; - } - - get last(): T | UNINITIALIZED { - return this.#value; - } } export const Formula = FormulaImpl.create; -export type Formula = FormulaFn; +export type Formula = Expand> & (() => T); diff --git a/packages/universal/reactive/src/primitives/marker.ts b/packages/universal/reactive/src/primitives/marker.ts index fff68306..2cf83487 100644 --- a/packages/universal/reactive/src/primitives/marker.ts +++ b/packages/universal/reactive/src/primitives/marker.ts @@ -1,18 +1,20 @@ import { readonly } from "@starbeam/core-utils"; import { Desc, type Description } from "@starbeam/debug"; -import { type CellTag as ICellTag, type Tagged } from "@starbeam/interfaces"; +import { + type CellTag as ICellTag, + type Expand, + type Tagged, +} from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { CellTag } from "@starbeam/tags"; import { getRuntime } from "../runtime.js"; -import type { PrimitiveOptions } from "./shared.js"; +import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; class MarkerImpl implements Tagged { - static create( - this: void, - { description }: PrimitiveOptions = {} - ): MarkerImpl { - return new MarkerImpl(Desc("cell", description)); + static create(this: void, options?: SugaryPrimitiveOptions): MarkerImpl { + const { description } = toOptions(options); + return new MarkerImpl(Desc("cell", Desc("cell", description))); } declare readonly [TAG]: ICellTag; @@ -21,8 +23,8 @@ class MarkerImpl implements Tagged { readonly(this, TAG, CellTag.create(description)); } - read(caller = getRuntime().callerStack()): void { - this[TAG].update({ stack: caller, runtime: getRuntime() }); + read(_caller = getRuntime().callerStack()): void { + getRuntime().autotracking.consume(this[TAG]); } freeze(): void { @@ -30,9 +32,9 @@ class MarkerImpl implements Tagged { } mark(caller = getRuntime().callerStack()): void { - this[TAG].update({ stack: caller, runtime: getRuntime() }); + this[TAG].update({ caller, runtime: getRuntime() }); } } export const Marker = MarkerImpl.create; -export type Marker = MarkerImpl; +export type Marker = Expand; diff --git a/packages/universal/reactive/src/primitives/shared.ts b/packages/universal/reactive/src/primitives/shared.ts deleted file mode 100644 index 1fabd361..00000000 --- a/packages/universal/reactive/src/primitives/shared.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Description } from "@starbeam/debug"; - -export interface PrimitiveOptions { - description?: string | Description; -} diff --git a/packages/universal/reactive/src/primitives/static.ts b/packages/universal/reactive/src/primitives/static.ts index a63f7593..d76e075f 100644 --- a/packages/universal/reactive/src/primitives/static.ts +++ b/packages/universal/reactive/src/primitives/static.ts @@ -4,7 +4,7 @@ import type * as interfaces from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { StaticTag } from "@starbeam/tags"; -import type { PrimitiveOptions } from "./shared.js"; +import type { PrimitiveOptions } from "./utils.js"; export class StaticImpl implements interfaces.ReactiveValue diff --git a/packages/universal/reactive/src/primitives/utils.ts b/packages/universal/reactive/src/primitives/utils.ts new file mode 100644 index 00000000..f9b2dc47 --- /dev/null +++ b/packages/universal/reactive/src/primitives/utils.ts @@ -0,0 +1,59 @@ +import type { Description } from "@starbeam/debug"; +import type { ReactiveValue, TaggedReactive } from "@starbeam/interfaces"; +import { TAG } from "@starbeam/shared"; +import type { FormulaTag } from "@starbeam/tags"; + +import { RUNTIME } from "../runtime.js"; + +export interface PrimitiveOptions { + description?: DescriptionOption; +} + +/** + * If a string is passed as options to a primitive, it's the description. + */ +export type DescriptionOption = string | Description | undefined; + +export type SugaryPrimitiveOptions = PrimitiveOptions | DescriptionOption; + +export function isDescriptionOption( + options: SugaryPrimitiveOptions +): options is DescriptionOption { + return ( + options === undefined || typeof options === "string" || "id" in options + ); +} + +export function toOptions(options: SugaryPrimitiveOptions): PrimitiveOptions { + if (isDescriptionOption(options)) { + return { description: options }; + } else { + return options; + } +} + +export interface FormulaFn extends TaggedReactive { + (): T; +} + +export function WrapFn(formula: ReactiveValue): FormulaFn { + const fn = (): T => { + return formula.read(RUNTIME.callerStack()); + }; + + Object.defineProperties(fn, { + current: { + get: fn, + }, + [TAG]: { + get: () => formula[TAG], + }, + read: { + value: fn, + }, + }); + + return fn as FormulaFn; +} + +export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index 8005d542..a8d02dfb 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -1,4 +1,11 @@ -import type { Runtime } from "@starbeam/interfaces"; +import type { + AutotrackingRuntime, + DeprecatedTimeline, + Runtime, + Stack, + SubscriptionRuntime, + Tag, +} from "@starbeam/interfaces"; export const CONTEXT = { runtime: null as null | Runtime, @@ -19,3 +26,34 @@ export function getRuntime(): Runtime { return CONTEXT.runtime as Runtime; } + +class RuntimeImpl implements Runtime { + callerStack(): Stack { + return getRuntime().callerStack(); + } + + get timeline(): DeprecatedTimeline { + return getRuntime().timeline; + } + + get subscriptions(): SubscriptionRuntime { + return getRuntime().subscriptions; + } + + get autotracking(): AutotrackingRuntime { + return getRuntime().autotracking; + } + + evaluate(compute: () => T): { value: T; tags: Set } { + const done = this.autotracking.start(); + const value = compute(); + const tags = done(); + return { value, tags }; + } + + // timeline: DeprecatedTimeline; + // subscriptions: SubscriptionRuntime; + // autotracking: AutotrackingRuntime; +} + +export const RUNTIME = new RuntimeImpl(); diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index 93ec8cf6..cc61d93c 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -22,6 +22,7 @@ export { export { PUBLIC_TIMELINE, type PublicTimeline, + ReactiveError, SUBSCRIPTION_RUNTIME, } from "./src/timeline/tracker.js"; export { diff } from "./src/timeline/utils.js"; diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index 6f9e95bc..41106a0b 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -16,6 +16,12 @@ enum Phase { write = "write", } +export class ReactiveError extends Error { + constructor(message: string) { + super(message); + } +} + /** * The Timeline is the core of the runtime. * @@ -28,6 +34,14 @@ class Mutations implements SubscriptionRuntime { readonly #lastPhase: Phase = Phase.read; subscribe(target: Tag, ready: NotifyReady): Unsubscribe { + if (target.tdz) { + throw new ReactiveError( + `The tag ${target.description.describe({ + color: false, + })} isn't initialized yet, so you can't subscribe to it. This is a bug in the implementation of a primitive or renderer.` + ); + } + return this.#subscriptions.register(target, ready); } diff --git a/packages/universal/runtime/tests/consume.spec.ts b/packages/universal/runtime/tests/consume.spec.ts index 4a79e706..b1474439 100644 --- a/packages/universal/runtime/tests/consume.spec.ts +++ b/packages/universal/runtime/tests/consume.spec.ts @@ -1,7 +1,6 @@ -import { Desc, Stack } from "@starbeam/debug"; -import { Cell, Formula, getRuntime, Marker } from "@starbeam/reactive"; +import { Desc } from "@starbeam/debug"; +import { CachedFormula, Cell, getRuntime, Marker } from "@starbeam/reactive"; import { getTag } from "@starbeam/runtime"; -import { getID } from "@starbeam/shared"; import { FormulaTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; @@ -12,7 +11,7 @@ const RUNTIME = getRuntime(); describe("consumption", () => { test("the basics", () => { const number = Cell(1); - const double = Formula(() => number.current * 2); + const double = CachedFormula(() => number.current * 2); expect(double.current).toBe(2); @@ -21,27 +20,20 @@ describe("consumption", () => { expect(double.current).toBe(4); }); - test("in the context of a frame", () => { + test("the primitive autotracking protocol", () => { const instance = Marker(); - const id = getID(); - const here = Stack.fromCaller(-1); + // start an autotracking frame const done = RUNTIME.autotracking.start(); + // consume the marker's tag in the autotracking frame RUNTIME.autotracking.consume(getTag(instance)); + // finalize the frame, which should give us back the marker's tag const tags = done(); + // create a formula tag with the marker's tags const tag = FormulaTag.create(Desc("formula"), () => tags); - // const frame = TIMELINE.frame.evaluate( - // () => { - // TIMELINE.didConsumeCell(getTag(instance), here); - // }, - // { - // description: descriptionFrom({ - // id, - // type: "formula", - // api: "Formula", - // }), - // } - // ); + // unset the tag's TDZ, which will allow subscriptions to the tag. Normally + // this happens in the implementation of `Formula`, once the value was computed. + tag.unsetTdz(); const stale = new Staleness(); RUNTIME.subscriptions.subscribe(tag, () => { @@ -59,11 +51,11 @@ describe("consumption", () => { const cellB = Cell(2); const cellC = Cell(3); - const doubleA = Formula(() => cellA.current * 2); - const doubleB = Formula(() => cellB.current * 2); - const doubleC = Formula(() => cellC.current * 2); + const doubleA = CachedFormula(() => cellA.current * 2); + const doubleB = CachedFormula(() => cellB.current * 2); + const doubleC = CachedFormula(() => cellC.current * 2); - const sum = Formula(() => { + const sum = CachedFormula(() => { const abSum = doubleA.current + doubleB.current; if (abSum > 15) { @@ -74,12 +66,13 @@ describe("consumption", () => { }); const stale = new Staleness(); + expect(sum.current).toBe(6); + const unsubscribe = RUNTIME.subscriptions.subscribe(getTag(sum), () => { stale.invalidate(); }); stale.expect("fresh"); - expect(sum.current).toBe(6); stale.expect(() => (cellA.current += 2), "stale"); expect(sum.current).toBe(10); diff --git a/packages/universal/runtime/tests/subscribing.spec.ts b/packages/universal/runtime/tests/subscribing.spec.ts index 3d4507be..96b6d936 100644 --- a/packages/universal/runtime/tests/subscribing.spec.ts +++ b/packages/universal/runtime/tests/subscribing.spec.ts @@ -1,8 +1,8 @@ import { isPresentArray } from "@starbeam/core-utils"; -import { Desc } from "@starbeam/debug"; +import { Desc, logTag } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; -import { Cell, Formula } from "@starbeam/reactive"; -import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; +import { CachedFormula,Cell } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE, ReactiveError, TAG } from "@starbeam/runtime"; import { DelegateTag, getTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; @@ -25,17 +25,26 @@ describe("Tagged", () => { expect(cell.current).toBe(1); }); + test("subscribing to a formula before reading it is an error", () => { + const cell = Cell(0); + const formula = CachedFormula(() => cell.current); + + expect(() => PUBLIC_TIMELINE.on.change(formula, () => void 0)).toThrow( + ReactiveError + ); + }); + test("subscribing to a formula", () => { let stale = false; const { sum, numbers } = Sum(); + expect(sum.read()).toBe(0); PUBLIC_TIMELINE.on.change(sum, () => { stale = true; }); expect(stale).toBe(false); - expect(sum.read()).toBe(0); numbers.current = [...numbers.current, Cell(1), Cell(2)]; @@ -81,15 +90,34 @@ describe("Tagged", () => { expect(cell.current).toBe(1); }); - test("subscribing to a delegate with a composite", () => { + test("subscribing to a formula before reading one of its formula targets is an error", () => { + const cell = Cell(0); + const formula = CachedFormula(() => cell.current); + + const delegate: ReactiveValue = { + read: () => formula.current, + [TAG]: DelegateTag.create(Desc("delegate", "test delegate"), [ + getTag(formula), + ]), + }; + + expect(() => PUBLIC_TIMELINE.on.change(delegate, () => void 0)).toThrow( + ReactiveError + ); + }); + + test("subscribing to a formula delegate", () => { const { sum, numbers } = Sum(); const delegate: ReactiveValue = { read: () => sum.read(), - [TAG]: DelegateTag.create(Desc("delegate"), [getTag(sum)]), + [TAG]: DelegateTag.create(Desc("delegate", "test delegate"), [ + getTag(sum), + ]), }; let stale = false; + expect(delegate.read()).toBe(0); const unsubscribe = PUBLIC_TIMELINE.on.change(delegate, () => { stale = true; @@ -97,14 +125,14 @@ describe("Tagged", () => { expect(stale).toBe(false); - numbers.current = [...numbers.current, Cell(1), Cell(2)]; - - // The pollable doesn't fire because we didn't update the reactive. - expect(stale).toBe(false); + numbers.current = [...numbers.current, Cell(1, "one"), Cell(2, "two")]; expect(delegate.read()).toBe(3); + logTag(delegate[TAG]); satisfying(numbers.current, isPresentArray)[0].current++; + logTag(delegate[TAG]); + expect(stale).toBe(true); stale = false; @@ -127,10 +155,12 @@ function Sum(): { sum: ReactiveValue; numbers: Cell[]>; } { - const numbers = Cell([] as Cell[]); + const description = Desc("formula", "Sum"); + const numbers = Cell([] as Cell[], "number list"); - const sum = Formula(() => - numbers.current.reduce((acc, cell) => acc + cell.current, 0) + const sum = CachedFormula( + () => numbers.current.reduce((acc, cell) => acc + cell.current, 0), + description ); return { sum, numbers }; diff --git a/packages/universal/runtime/tests/subscription.spec.ts b/packages/universal/runtime/tests/subscription.spec.ts index e1fff728..3b89cbdb 100644 --- a/packages/universal/runtime/tests/subscription.spec.ts +++ b/packages/universal/runtime/tests/subscription.spec.ts @@ -1,45 +1,22 @@ -import { Cell, Formula } from "@starbeam/reactive"; -import { PUBLIC_TIMELINE } from "@starbeam/runtime"; +import { CachedFormula, Cell } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE, ReactiveError } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; describe("frames", () => { test("subscription before first consumption", () => { const cell = Cell("Tom Dale"); - const formula = Formula(() => cell.current); + const formula = CachedFormula(() => cell.current); - let stale = false; - - const unsubscribe = PUBLIC_TIMELINE.on.change(formula, () => { - stale = true; - }); - - expect(formula.current).toBe("Tom Dale"); - - // The pollable doesn't fire initially. - expect(stale).toBe(false); - - // The pollable fires after the cell changes. - cell.current = "Jerry Seinfeld"; - expect(stale).toBe(true); - stale = false; - - expect(formula.read()).toBe("Jerry Seinfeld"); - - unsubscribe(); - - cell.current = "J. Seinfeld"; - // the subscription doesn't fire after it was ubsubscribed - expect(stale).toBe(false); - - // The lack of a subscription doesn't make the value incorrect - expect(formula.current).toBe("J. Seinfeld"); + expect(() => PUBLIC_TIMELINE.on.change(formula, () => void 0)).toThrow( + ReactiveError + ); }); test("subscription after first consumption", () => { const cell = Cell("Tom Dale"); - const formula = Formula(() => cell.current); + const formula = CachedFormula(() => cell.current); let stale = false; diff --git a/packages/universal/tags/README.md b/packages/universal/tags/README.md new file mode 100644 index 00000000..ef7e0de3 --- /dev/null +++ b/packages/universal/tags/README.md @@ -0,0 +1,185 @@ +This package contains the implementation of "tags". + +All reactive value are tagged values: they represent a JavaScript value and have +a tag that can be used to composably validate the value. + +## Tags are not dirty bits + +The problem with simply marking a value as dirty when it changes is simple: +multiple consumers. + +If you mark a value as dirty, then you need to mark it as clean at some point in +the future. But if the value has multiple consumers, when do you mark it as +clean? + +Tags solve this problem by associating a value with a revision: the last time +the value was modified on the global revision timeline. + +After retrieving the value of a reactive, the tag will tell you the timestamp +when it was last updated (its "revision"). Later, if you want to check whether +the value may have changed, you can ask the tag for its revision again. If the +revision has advanced, that means that whatever you did with the value needs to +be updated. + +## Tags are composable + +Defined this way, it becomes easy to compose multiple tags. + +If you computed something using multiple reactive values, you ask each of their +tags (the "child tags") for their revision. The revision of the computation is +the maximum of the revision of its child tags. + +If you want to know whether the computation is stale, you ask each of its child +tags for its revision again and compute the maximum of the revisions. If the new +maximum is greater than the old maximum, then the computation is stale. + +## Fundamental Properties of Tags + +Tags have these fundamental properties: + +- A `description` property. This is a rich object that enables the logging and + debugging features of Starbeam. +- A `lastUpdated` property. In composite tags, this is the latest revision of + the tag's children. +- An `id` property. This is a unique identifier for the tag that does not change + over its lifetime. It can be a string, a number or an array of IDs (recursive). +- A `dependencies()` method. This returns a list of [cell tags] that the tag + currently depends on. This list can change over time, so it must not be + cached. + +## The Tags + +### Cell Tags + +Cell tags represent the most granular changes to reactive values. + +In addition to the fundamental properties, they have the following additional +properties: + +- An `isFrozen()` method. This method may return `true` if the value the tag + represents will not change in the future. Once a cell tag becomes frozen, + subscribers to the tag are free to unsubscribe. +- A `freeze()` method. This method marks the tag as frozen (which means that + `isFrozen()` will return true after this point). Freezing a tag does not + increment its revision counter: if a consumer of the tag is up-to-date, + freezing the tag does not require the consumer to handle changes to its value. +- An `update()` method. This method indicates that the tag's underlying storage + has changed. Calling this method updates the `lastUpdated` property to the + current timestamp. + +A cell tag's `dependencies()` are: + +- empty when the cell is frozen +- the cell itself when the cell is not frozen + +### Static Tags + +A static tag represents a value that can never change. Unlike a frozen cell tag, +which represents data that may have changed in the past, a static tag represents +data that has always been the same. + +There is never any reason to subscribe to a static tag, and they are never +included in a tag's `dependendencies()` list. + +They primarily exist to model parameters that could either be `T` or +`Reactive`, where a `T` parameter is coerced into `Static` with a static +tag. + +### Formula Tags + +A formula tag represents a reactive computation whose component tags can change +when the value is recomputed. + +Its `lastUpdated` property is the latest revision of its current children. + +Its `dependencies()` method returns a list of the cells that its current children +depend on. This is a recursive process that returns a flattened list of the cell +tags that the formula tag transitively depends on. + +In addition to the fundamental properties, a formula tag has the following +additional properties: + +- A `tdz` ("temporal dead zone") property. This property is true when the + computation that this tag represents has not yet been evaluated. Subscribing + to a formula tag in the `tdz` state is semantically invalid. Attempting to do + so indicates a mistake in the implementation. +- An `unsetTDZ()` method, which sets the `tdz` property to `false`. + +### Delegate Tags + +A delegate tag represents a reactive computation whose component tags _will not +change_ over the lifetime of the tag. + +It exists to make it possible to create abstractions around underlying reactive +values, but allow subscribers to those abstractions to subscribe directly to the +component tags. + +Semantically, you can think of a delegate tag as a special kind of formula tag. + +## Tag Composition + +The primary composition in Starbeam is **value composition**. This means that +Starbeam code typically works at the value level: + +```ts +const a = Cell(0); +const b = Cell(0); + +const c = Formula(() => a.current + b.current); + +console.log(c.current); // 0 + +a.current++; + +console.log(c.current); // 1 +``` + +This code doesn't refer to tags at all, and that's true about the primary +programming model of Starbeam: using cells to store reactive values and using +functions to perform computations on reactive values. + +In Starbeam, tags are used for two purposes: + +1. To enable reactive caching (i.e. `CachedFormula`). A reactive cache is + invalidated when any of the cells used in its last evaluation (its current dependencies) change. +2. To enable rendering. Rendering is the process of converting a reactive value + into a representation that's outside of the reactive system and keeping it up + to date as the reactive value changes. + +### Reactive Caches + +A reactive cache is implemented as a reactive value. Its `lastUpdated` value is +simply the latest revision of its current dependencies. By implementing a +reactive cache this way, they can be used in other parts of a reactive system +(including in private fields and the internals of other abstractions) without +needing to subscribe along the way. + +### Rendering + +The Starbeam rendering pattern is: + +1. Get the current value of a reactive. +2. Render it. +3. Get the tag for the reactive. +4. When the tag is invalidated, update the rendering. + +You can think of rendering as a way to create reactive outputs. For example, +even though Starbeam is not aware of the DOM, you can use a renderer to create a +"reactive DOM node". + +Similarly, you can use a renderer to bridge between Starbeam reactivity and an +external reactive system, including frameworks like React and Vue, and reactive +libraries like D3. + +Subscriptions in Starbeam power rendering. + +A subscription is only semantically valid to keep a concrete value up to date. +This means that subscribing to a formula that hasn't yet been computed is +semantically invalid and will produce an error. + +This is only true of subscriptions: computing the _value_ of a formula is always +valid, even when the formula hasn't been computed yet (that's the whole point). + +> **TL;DR** getting "the current revision" of a formula that hasn't yet been +> computed doesn't make sense. Intuitively, this is because you can't render an +> unevaluated formula (you can only render a formula's value). diff --git a/packages/universal/tags/index.ts b/packages/universal/tags/index.ts index d8ba9811..3f31b58c 100644 --- a/packages/universal/tags/index.ts +++ b/packages/universal/tags/index.ts @@ -1,4 +1,12 @@ -export { CellTag, DelegateTag, FormulaTag, StaticTag, Tag } from "./src/tag.js"; +export { + CellTag, + DelegateTag, + FormulaTag, + StaticTag, + /** @deprecated */ + Tag, + Tag as TagUtils, +} from "./src/tag.js"; export { dependenciesInTaggedList, describeTagged, diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index 5d81c433..9587ed28 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -1,9 +1,12 @@ +import { DisplayStruct } from "@starbeam/debug"; import type { Description, UpdateOptions } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; import { type Timestamp, zero } from "./timestamp.js"; import { NOW } from "./timestamp.js"; +const INSPECT = Symbol.for("nodejs.util.inspect.custom"); + export abstract class Tag implements interfaces.AbstractTag, interfaces.TagMethods { @@ -32,6 +35,8 @@ export abstract class Tag } abstract readonly type: interfaces.TagType; + abstract readonly tdz: boolean; + readonly #description: Description; constructor(description: Description) { this.#description = description; @@ -75,6 +80,7 @@ export class CellTag extends Tag implements interfaces.CellTag { } readonly type = "cell"; + readonly tdz = false; #frozen = false; #lastUpdated: Timestamp; @@ -84,6 +90,13 @@ export class CellTag extends Tag implements interfaces.CellTag { this.#lastUpdated = lastUpdated; } + [INSPECT]() { + return DisplayStruct("Cell", { + id: this.description.id, + lastUpdated: this.lastUpdated, + }); + } + isFrozen() { return this.#frozen; } @@ -119,6 +132,7 @@ export class StaticTag extends Tag implements interfaces.StaticTag { } readonly type = "static"; + readonly tdz = false; override readonly lastUpdated = NOW.now; @@ -132,18 +146,29 @@ export class FormulaTag extends Tag implements interfaces.FormulaTag { description: Description, children: () => interfaces.List ): FormulaTag { - return new FormulaTag(description, children); + return new FormulaTag(description, children, true); } readonly type = "formula"; readonly #children: () => interfaces.List; + #tdz: boolean; private constructor( description: Description, - children: () => interfaces.List + children: () => interfaces.List, + tdz: boolean ) { super(description); this.#children = children; + this.#tdz = tdz; + } + + get tdz(): boolean { + return this.#tdz; + } + + unsetTdz(): void { + this.#tdz = false; } children(): readonly interfaces.Tag[] { @@ -186,6 +211,10 @@ export class DelegateTag extends Tag implements interfaces.DelegateTag { this.#targets = targets; } + get tdz(): boolean { + return this.#targets.some((target) => target.tdz); + } + get targets(): readonly interfaces.Tag[] { return this.#targets; } diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 79e37b32..276b394f 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -6,10 +6,6 @@ export { } from "./src/reactive-core/custom.js"; export { Wrap } from "./src/reactive-core/delegate.js"; export { Linkable } from "./src/reactive-core/formula/linkable.js"; -export { - PolledFormula, - PolledFormulaValidation, -} from "./src/reactive-core/formula/polled-formula.js"; export { Setup, Setups } from "./src/reactive-core/formula/setups.js"; export { Freshness } from "./src/reactive-core/higher-level/freshness.js"; export { @@ -48,5 +44,12 @@ export { Variants, type VariantType, } from "./src/reactive-core/variants.js"; -export { Cell, type Equality, Formula, Static } from "@starbeam/reactive"; +export { + Cell, + type Equality, + // FIXME: Migrate these to their ultimate names + CachedFormula as Formula, + Formula as PolledFormula, + Static, +} from "@starbeam/reactive"; export { LIFETIME, PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; diff --git a/packages/universal/universal/src/debug-renderer.ts b/packages/universal/universal/src/debug-renderer.ts index 5bdfedeb..fa221ddc 100644 --- a/packages/universal/universal/src/debug-renderer.ts +++ b/packages/universal/universal/src/debug-renderer.ts @@ -1,9 +1,8 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; import type { Unsubscribe } from "@starbeam/interfaces"; +import { Formula } from "@starbeam/reactive"; import { PUBLIC_TIMELINE } from "@starbeam/runtime"; -import { Formula } from "./reactive-core/formula/formula.js"; - export const DEBUG_RENDERER = { render( { diff --git a/packages/universal/universal/src/reactive-core/formula/formula.ts b/packages/universal/universal/src/reactive-core/formula/formula.ts deleted file mode 100644 index 857c2b49..00000000 --- a/packages/universal/universal/src/reactive-core/formula/formula.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - callerStack, - type Description, - descriptionFrom, -} from "@starbeam/debug"; -import type { Reactive, Stack } from "@starbeam/interfaces"; -import { diff, Frame, TAG } from "@starbeam/runtime"; -import type { UNINITIALIZED } from "@starbeam/shared"; -import { DelegateTag, getTag } from "@starbeam/tags"; - -export interface FormulaValidation { - frame: Frame; - poll: () => Frame; -} - -export function FormulaValidation( - callback: () => T, - description?: Description | string -): FormulaValidation { - const desc = descriptionFrom({ - type: "formula", - api: { - package: "@starbeam/universal", - name: "Formula", - }, - fromUser: description, - }); - - const frame = Frame.uninitialized(TIMELINE.now, desc); - - const update = (caller: Stack): void => { - if (import.meta.env.DEV) { - const oldDeps = new Set(getTag(frame).dependencies()); - - frame.evaluate(callback, TIMELINE.frame); - - TIMELINE.update(frame); - - const newDeps = new Set(getTag(frame).dependencies()); - - TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); - } else { - frame.evaluate(callback, TIMELINE.frame); - TIMELINE.update(frame); - TIMELINE.didConsumeFrame(frame, diff.empty(), caller); - } - }; - - function poll(caller = callerStack()): Frame { - const validation = frame.validate(); - - if (validation.status === "valid") { - TIMELINE.didConsumeFrame(frame, diff.empty(), caller); - return frame; - } else { - update(caller); - } - - return frame; - } - - return { poll, frame }; -} - -export interface Formula extends Reactive { - (): T; - readonly current: T; -} - -export function Formula( - callback: () => T, - description?: Description | string -): Formula { - const desc = descriptionFrom({ - type: "formula", - api: { - package: "@starbeam/universal", - name: "Formula", - }, - fromUser: description, - }); - - const formula = FormulaValidation(callback, desc); - - const fn = (): T => Frame.value(formula.poll()); - - Object.defineProperty(fn, "read", { - enumerable: false, - configurable: true, - writable: true, - value: fn, - }); - - Object.defineProperty(fn, "current", { - enumerable: false, - configurable: true, - get: fn, - }); - - Object.defineProperty(fn, TAG, { - enumerable: false, - configurable: true, - writable: true, - value: DelegateTag.create(desc, [getTag(formula.frame)]), - }); - - Object.defineProperty(fn, Symbol.for("nodejs.util.inspect.custom"), { - enumerable: false, - configurable: true, - writable: true, - value: () => { - return `Formula(${desc.fullName}, id=${JSON.stringify(desc.id)})`; - }, - }); - - return fn as Formula; -} diff --git a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts b/packages/universal/universal/src/reactive-core/formula/polled-formula.ts deleted file mode 100644 index ce08e202..00000000 --- a/packages/universal/universal/src/reactive-core/formula/polled-formula.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - callerStack, - Desc, - type Description, - descriptionFrom, -} from "@starbeam/debug"; -import type { Stack } from "@starbeam/interfaces"; -import { diff, Frame, TAG } from "@starbeam/runtime"; -import type { UNINITIALIZED } from "@starbeam/shared"; -import { DelegateTag, getTag } from "@starbeam/tags"; - -import type { Formula } from "./formula.js"; - -/** - * A {@linkcode PolledFormula} is like a {@linkcode Formula}, but it never attempts to avoid running the - * formula function when the formula is still valid. - * - * Its purpose is to provide notifications if any reactive dependency is invalidated, but not get in - * the way of other kinds of polling-style reactive notifications coming from a framework. - * - * In other words, it is a way to create a reactive formula in an environment that will be - * invalidated by framework polling (and a framework-specific dependency tracking mechanism), but - * wants to mix in Starbeam's notification mechanism for Starbeam dependencies. - */ - -export function PolledFormulaValidation( - callback: () => T, - description?: Description | string -): { - frame: Frame; - poll: () => Frame; - update: (caller?: Stack) => void; -} { - const desc = descriptionFrom({ - type: "formula", - api: { - package: "@starbeam/universal", - name: "Formula", - }, - fromUser: description, - }); - - const frame = Frame.uninitialized(TIMELINE.now, desc); - - const update = (caller: Stack = callerStack()): void => { - if (import.meta.env.DEV) { - const oldDeps = new Set(getTag(frame).dependencies()); - - frame.evaluate(callback, TIMELINE.frame); - TIMELINE.update(frame); - - const newDeps = new Set(getTag(frame).dependencies()); - - TIMELINE.didConsumeFrame(frame, diff(oldDeps, newDeps), caller); - } else { - frame.evaluate(callback, TIMELINE.frame); - TIMELINE.update(frame); - TIMELINE.didConsumeFrame(frame, diff.empty(), caller); - } - }; - - function poll(caller = callerStack()): Frame { - update(caller); - - return frame as Frame; - } - - return { poll, update, frame }; -} - -export function PolledFormula( - callback: () => T, - description?: Description | string -): Formula { - const desc = Desc("formula", description).forApi({ - package: "@starbeam/universal", - name: "PolledFormula", - }); - const formula = PolledFormulaValidation(callback, desc); - - const fn = (): T => Frame.value(formula.poll()); - - Object.defineProperty(fn, "read", { - enumerable: false, - configurable: true, - writable: true, - value: fn, - }); - - Object.defineProperty(fn, "current", { - enumerable: false, - configurable: true, - get: fn, - }); - - Object.defineProperty(fn, TAG, { - enumerable: false, - configurable: true, - writable: true, - value: DelegateTag.create(desc, [getTag(formula.frame)]), - }); - - return fn as Formula; -} diff --git a/packages/universal/universal/src/reactive-core/formula/setups.ts b/packages/universal/universal/src/reactive-core/formula/setups.ts index 2db82552..1bf77026 100644 --- a/packages/universal/universal/src/reactive-core/formula/setups.ts +++ b/packages/universal/universal/src/reactive-core/formula/setups.ts @@ -1,9 +1,8 @@ import { type Description, descriptionFrom } from "@starbeam/debug"; -import { Marker } from "@starbeam/reactive"; +import { Formula, Marker } from "@starbeam/reactive"; import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; import { getID } from "@starbeam/shared"; -import { Formula } from "./formula.js"; type SetupFunction = (() => void) | (() => () => void); export type Setup = Formula; diff --git a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts index 742dbd79..e1d1b7f6 100644 --- a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts +++ b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts @@ -1,6 +1,6 @@ import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; +import { CachedFormula, Formula } from "@starbeam/reactive"; -import { Formula } from "../formula/formula.js"; import type { AssimilatedResourceReturn, ResourceBlueprint, @@ -58,7 +58,7 @@ export function FormulaList( if (r) { result.push(r.read()); } else { - const newR = Formula(() => map(item)); + const newR = CachedFormula(() => map(item)); result.push(newR.current); prev.set(k, newR); } diff --git a/packages/universal/universal/src/reactive-core/resource/resource.ts b/packages/universal/universal/src/reactive-core/resource/resource.ts index 76380ab4..243df862 100644 --- a/packages/universal/universal/src/reactive-core/resource/resource.ts +++ b/packages/universal/universal/src/reactive-core/resource/resource.ts @@ -15,12 +15,11 @@ import { Desc, type Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; -import { Static } from "@starbeam/reactive"; +import { CachedFormula, Static } from "@starbeam/reactive"; import { LIFETIME } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; import { isWeakKey } from "@starbeam/verify"; -import { Formula } from "../formula/formula.js"; import type { IntoResource } from "../into.js"; import { type Blueprint, ReactiveBlueprint } from "../reactive.js"; import type { ResourceRun } from "./run.js"; @@ -145,7 +144,7 @@ export class ResourceBlueprint { } initial(value: () => T): ResourceBlueprint { - return new ResourceBlueprint(this.#create, this.#use, Formula(value)); + return new ResourceBlueprint(this.#create, this.#use, CachedFormula(value)); } #link({ state }: InternalBlueprintReturn): Resource { diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts index af21efdb..ed4e4053 100644 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ b/packages/universal/universal/src/reactive-core/resource/state.ts @@ -1,10 +1,9 @@ import type { Description } from "@starbeam/debug"; import type { Reactive } from "@starbeam/interfaces"; -import { isReactive, Static } from "@starbeam/reactive"; +import { CachedFormula, isReactive, Static } from "@starbeam/reactive"; import { LIFETIME } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; -import { Formula } from "../formula/formula.js"; import { type AssimilatedResourceReturn, brandResource, @@ -74,7 +73,7 @@ export class ResourceState { this.#constructorFn = constructorFn; this.#owner = owner; - this.reactiveConstructor = Formula( + this.reactiveConstructor = CachedFormula( () => this.next(), desc.detail("constructor") ); @@ -86,7 +85,7 @@ export class ResourceState { finalized = true; }); - this.reactiveInstance = Formula(() => { + this.reactiveInstance = CachedFormula(() => { if (instance && finalized) return instance; instance = this.reactiveConstructor.read(); @@ -94,7 +93,7 @@ export class ResourceState { }, desc.detail("instance")); this.resource = brandResource( - Formula( + CachedFormula( () => this.reactiveInstance.read().read(), desc.detail("instance") ) diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 0b1ad2e6..1668c694 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -26,6 +26,8 @@ describe("Variants", () => { const bool = Bool.true(); const type = Formula(() => bool.current.type); + expect(type.current).toBe("true"); + const typeStable = Stability(type); expect(type.current).toBe("true"); @@ -83,34 +85,41 @@ describe("Variants", () => { { description: "advance" } ); - const render = Formula((): number | Error | "idle" | "loading" => { - advance(); - - if (lifecycle.is("idle")) { - return "idle"; - } else if (lifecycle.is("loading")) { - return "loading"; - } else if (lifecycle.is("loaded")) { - return lifecycle.current.value; - } else if (lifecycle.is("error")) { - return lifecycle.current.value; - } else { - throw Error("unreachable"); - } - }, {description: "render"}); + const render = Formula( + (): number | Error | "idle" | "loading" => { + advance(); + + if (lifecycle.is("idle")) { + return "idle"; + } else if (lifecycle.is("loading")) { + return "loading"; + } else if (lifecycle.is("loaded")) { + return lifecycle.current.value; + } else if (lifecycle.is("error")) { + return lifecycle.current.value; + } else { + throw Error("unreachable"); + } + }, + { description: "render" } + ); + + const value = Formula( + () => { + return lifecycle.match({ + loaded: (v) => v, + }); + }, + { description: "value" } + ); - const value = Formula(() => { - return lifecycle.match({ - loaded: (v) => v, - }); - }, {description: "value"}); + expect(render()).toBe("loading"); + expect(value()).toBe(undefined); const advanceStable = Stability(advance); const renderStable = Stability(render); const valueStable = Stability(value); - expect(render()).toBe("loading"); - expect(value()).toBe(undefined); expect(advanceStable.changed).toBe(false); expect(renderStable.changed).toBe(false); expect(valueStable.changed).toBe(false); @@ -174,9 +183,9 @@ describe("Variants", () => { return lifecycle.is("loaded", "error"); }); + expect(isResolved()).toBe(false); const isStable = Stability(isResolved); - expect(isResolved()).toBe(false); expect(isStable.changed).toBe(false); lifecycle.choose("loading"); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91c4d060..41fd59a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -408,9 +408,11 @@ importers: '@starbeam-dev/build-support': workspace:* '@starbeam/core-utils': workspace:^ '@starbeam/debug': workspace:^ + '@starbeam/interfaces': workspace:^ '@starbeam/preact-utils': workspace:^ '@starbeam/reactive': workspace:^ '@starbeam/runtime': workspace:^ + '@starbeam/tags': workspace:^ '@starbeam/universal': workspace:^ '@starbeam/verify': workspace:^ chalk: ^5.2.0 @@ -419,9 +421,11 @@ importers: dependencies: '@starbeam/core-utils': link:../../universal/core-utils '@starbeam/debug': link:../../universal/debug + '@starbeam/interfaces': link:../../universal/interfaces '@starbeam/preact-utils': link:../preact-utils '@starbeam/reactive': link:../../universal/reactive '@starbeam/runtime': link:../../universal/runtime + '@starbeam/tags': link:../../universal/tags '@starbeam/universal': link:../../universal/universal '@starbeam/verify': link:../../universal/verify preact: 10.11.3 From dba6a214b2a263433026427d338844500c78109a Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 28 Mar 2023 07:35:56 -0700 Subject: [PATCH 13/46] Add a hand-crafted resource test --- .../src/reactive-core/resource/core.ts | 0 .../universal/tests/hand-resource.spec.ts | 90 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 packages/universal/universal/src/reactive-core/resource/core.ts create mode 100644 packages/universal/universal/tests/hand-resource.spec.ts diff --git a/packages/universal/universal/src/reactive-core/resource/core.ts b/packages/universal/universal/src/reactive-core/resource/core.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/universal/universal/tests/hand-resource.spec.ts b/packages/universal/universal/tests/hand-resource.spec.ts new file mode 100644 index 00000000..c3b83480 --- /dev/null +++ b/packages/universal/universal/tests/hand-resource.spec.ts @@ -0,0 +1,90 @@ +import "@starbeam/runtime"; + +import type { Reactive } from "@starbeam/interfaces"; +import { CachedFormula, Cell } from "@starbeam/reactive"; +import { LIFETIME } from "@starbeam/runtime"; +import { describe, expect, test } from "vitest"; + +describe("A hand-rolled resource", () => { + test("works", () => { + const channelName = Cell("default"); + const resourceOwner = {}; + + function Channel(channelName: Reactive) { + const output = Cell(null as string | null); + const state: { + finalized: boolean; + cell: Cell; + channel: string | null; + counts: { init: number; cleanup: number }; + } = { + finalized: false, + cell: output, + channel: null, + counts: { init: 0, cleanup: 0 }, + }; + + function cleanup(): void { + state.channel = null; + state.counts.cleanup++; + state.cell.current = null; + } + + const formula = CachedFormula(() => { + if (state.channel) { + cleanup(); + } + + if (state.counts.init === 0) { + LIFETIME.on.cleanup(resourceOwner, () => { + cleanup(); + state.finalized = true; + }); + } + + if (!state.finalized) { + state.channel = channelName.current; + state.cell.current = channelName.current.toUpperCase(); + state.counts.init++; + } + + return state.cell; + }); + + const resource = CachedFormula(() => { + return formula.current.current; + }); + return { resource, state }; + } + + const { resource: channel, state } = Channel(channelName); + + expect(channel.current).toBe("DEFAULT"); + expect(state.counts.cleanup).toBe(0); + expect(state.counts.init).toBe(1); + expect(state.finalized).toBe(false); + + expect(channel.current).toBe("DEFAULT"); + expect(state.counts.cleanup).toBe(0); + expect(state.counts.init).toBe(1); + expect(state.finalized).toBe(false); + + channelName.set("newname"); + expect(channel.current).toBe("NEWNAME"); + expect(state.counts.cleanup).toBe(1); + expect(state.counts.init).toBe(2); + expect(state.finalized).toBe(false); + + LIFETIME.finalize(resourceOwner); + expect(channel.current).toBe(null); + expect(state.counts.cleanup).toBe(2); + expect(state.counts.init).toBe(2); + expect(state.finalized).toBe(true); + + channelName.set("newername"); + expect(channel.current).toBe(null); + expect(state.counts.cleanup).toBe(2); + expect(state.counts.init).toBe(2); + expect(state.finalized).toBe(true); + }); +}); From 276cba3c2b0c128961f5fd6c1838d7c9a7d65ac9 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 28 Mar 2023 16:08:52 -0700 Subject: [PATCH 14/46] WIP --- .../src/components/StockDetails.tsx | 2 +- packages/universal/reactive/index.ts | 1 + packages/universal/universal/index.ts | 12 +- .../reactive-core/formula/tracked-formula.ts | 0 .../higher-level/resource-list.ts | 4 +- .../universal/src/reactive-core/into.ts | 4 +- .../universal/src/reactive-core/reactive.ts | 2 +- .../{resource.ts => original-resource.ts} | 0 .../reactive-core/resource/resource-core.ts | 285 ++++++++++++++++++ .../src/reactive-core/resource/run.ts | 2 +- .../src/reactive-core/resource/state.ts | 2 +- .../universal/src/reactive-core/service.ts | 2 +- .../universal/tests/hand-resource.spec.ts | 277 ++++++++++++++++- .../universal/tests/resource.spec.ts | 24 -- 14 files changed, 580 insertions(+), 37 deletions(-) delete mode 100644 packages/universal/universal/src/reactive-core/formula/tracked-formula.ts rename packages/universal/universal/src/reactive-core/resource/{resource.ts => original-resource.ts} (100%) create mode 100644 packages/universal/universal/src/reactive-core/resource/resource-core.ts diff --git a/demos/react-stock-ticker/src/components/StockDetails.tsx b/demos/react-stock-ticker/src/components/StockDetails.tsx index 392eaad4..346b62a6 100644 --- a/demos/react-stock-ticker/src/components/StockDetails.tsx +++ b/demos/react-stock-ticker/src/components/StockDetails.tsx @@ -1,5 +1,5 @@ import { use, useReactive } from "@starbeam/react"; -import { type ResourceBlueprint, Cell, Resource } from "@starbeam/universal"; +import { Cell, Resource, type ResourceBlueprint } from "@starbeam/universal"; import { Portal } from "react-portal"; import { getDailyValues, getTickerDetails } from "../lib/api/api.js"; diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index a020d1ff..31ac2694 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -5,5 +5,6 @@ export { Formula } from "./src/primitives/formula.js"; export { FormulaLifecycle } from "./src/primitives/formula-lifecycle.js"; export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; +export { type FormulaFn } from "./src/primitives/utils.js"; export { defineRuntime, getRuntime } from "./src/runtime.js"; export { intoReactive, isReactive, read } from "./src/utils.js"; diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 276b394f..51dd3f5a 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -29,7 +29,17 @@ export { type ResourceBlueprint, type ResourceFactory, type ResourceReturn, -} from "./src/reactive-core/resource/resource.js"; +} from "./src/reactive-core/resource/original-resource.js"; +export { + assimilateResource, + CreateResourceRun, + getRunInstance, + ResourceConstructor, + ResourceInstance, + ResourceMetadata, + ResourceState, + updateResource, +} from "./src/reactive-core/resource/resource-core.js"; export type { ResourceRun } from "./src/reactive-core/resource/run.js"; export { createService, diff --git a/packages/universal/universal/src/reactive-core/formula/tracked-formula.ts b/packages/universal/universal/src/reactive-core/formula/tracked-formula.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts index e1d1b7f6..61996acd 100644 --- a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts +++ b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts @@ -5,8 +5,8 @@ import type { AssimilatedResourceReturn, ResourceBlueprint, ResourceReturn, -} from "../resource/resource.js"; -import { Resource } from "../resource/resource.js"; +} from "../resource/original-resource.js"; +import { Resource } from "../resource/original-resource.js"; export function ResourceList>( list: Iterable, diff --git a/packages/universal/universal/src/reactive-core/into.ts b/packages/universal/universal/src/reactive-core/into.ts index 79c6ce44..d085d810 100644 --- a/packages/universal/universal/src/reactive-core/into.ts +++ b/packages/universal/universal/src/reactive-core/into.ts @@ -4,8 +4,8 @@ import { intoReactive, isReactive } from "@starbeam/reactive"; import type { ReactiveBlueprint } from "./reactive.js"; import { type Blueprint, Reactive, type ReactiveFactory } from "./reactive.js"; -import { ResourceBlueprint } from "./resource/resource.js"; -import { Resource, type ResourceFactory } from "./resource/resource.js"; +import { ResourceBlueprint } from "./resource/original-resource.js"; +import { Resource, type ResourceFactory } from "./resource/original-resource.js"; export type IntoResource = | ResourceBlueprint diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index 26aeb209..9f8bcc5b 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -3,7 +3,7 @@ import type { ReactiveValue, Tag } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; import { isObject } from "@starbeam/verify"; -import type { ResourceBlueprint } from "./resource/resource.js"; +import type { ResourceBlueprint } from "./resource/original-resource.js"; export type ReactiveFactory = | (() => T) diff --git a/packages/universal/universal/src/reactive-core/resource/resource.ts b/packages/universal/universal/src/reactive-core/resource/original-resource.ts similarity index 100% rename from packages/universal/universal/src/reactive-core/resource/resource.ts rename to packages/universal/universal/src/reactive-core/resource/original-resource.ts diff --git a/packages/universal/universal/src/reactive-core/resource/resource-core.ts b/packages/universal/universal/src/reactive-core/resource/resource-core.ts new file mode 100644 index 00000000..0290a9fd --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/resource-core.ts @@ -0,0 +1,285 @@ +import type { Reactive, Unsubscribe } from "@starbeam/interfaces"; +import { CachedFormula, isReactive } from "@starbeam/reactive"; +import { LIFETIME } from "@starbeam/runtime"; +import { UNINITIALIZED } from "@starbeam/shared"; +import { isNotEqual, verified } from "@starbeam/verify"; + +type Cleanup = (metadata: M) => void; + +export class ResourceState { + static create( + update: UpdateResource, + metadata: M, + owner = {} + ): ResourceState { + const state = new ResourceState(update, metadata, owner); + LIFETIME.link(owner, state); + return state; + } + + static scoped( + update: UpdateResource, + metadata: M, + { owner, root }: { owner: object; root: object } + ): ResourceState { + const state = new ResourceState(update, metadata, owner); + LIFETIME.link(owner, state, { root }); + return state; + } + + /** + * The root lifetime of a resource is the lifetime of the top resource in a + * resource tree. Resources created within the root (via `use`) will be + * automatically adopted from one run to the next. + */ + #root: object; + #instance: T | UNINITIALIZED = UNINITIALIZED; + readonly #metadata: M; + readonly #update: UpdateResource; + #run: CreateResourceRun | null = null; + + /** + * Once the resource is finalized, its `nextRun` method will return + * `{done: true, metadata: metadata}`. + */ + #isFinalized = false; + + private constructor(update: UpdateResource, metadata: M, root: object) { + this.#update = update as UpdateResource; + this.#metadata = metadata; + this.#root = root; + + LIFETIME.on.cleanup(this, () => { + this.#isFinalized = true; + }); + } + + get #lastInstance(): T { + // The only way for this to happen is if the resource is finalized before it + // was ever consumed, and then it is consumed later. This should be avoided + // by construction, but there is still some work to do there. + return verified(this.#instance, isNotEqual(UNINITIALIZED)); + } + + adopt(parent: object, { root }: { root: object }): void { + LIFETIME.link(parent, this, { root }); + } + + nextRun(): RunResult { + if (this.#isFinalized) { + return finalized(this.#lastInstance, this.#metadata); + } + + const prevRun = this.#run; + + const run = this.#createRun(); + const result = next(this.#update(run, this.#metadata), this.#metadata); + this.#instance = result.value.instance; + + if (prevRun) LIFETIME.finalize(prevRun); + + return result; + } + + #createRun(): CreateResourceRun { + const run = (this.#run = CreateResourceRun.create( + this.#metadata, + this.#root + )); + LIFETIME.link(this, run); + return run; + } + + get isFinalized(): boolean { + return this.#isFinalized; + } + + get metadata(): M { + return this.#metadata; + } +} + +export class CreateResourceRun { + static create(metadata: M, root: object): CreateResourceRun { + return new CreateResourceRun(metadata, root); + } + + readonly #metadata: M; + readonly #root: object; + readonly #cleanups = new Set>(); + + private constructor(metadata: M, root: object) { + this.#metadata = metadata; + this.#root = root; + LIFETIME.on.cleanup(this, () => { + this.#cleanup(); + }); + } + + readonly on = { + cleanup: (fn: (metadata: M) => void): Unsubscribe => { + this.#cleanups.add(fn as Cleanup); + return () => this.#cleanups.delete(fn as Cleanup); + }, + }; + + use = ( + resource: ResourceConstructor | ResourceInstance + ): ResourceInstance => { + if (resource instanceof ResourceConstructorImpl) { + return resource.use({ within: this, root: this.#root }); + } else { + resource.adopt(this.#root); + return resource; + } + }; + + #cleanup(): void { + for (const cleanup of this.#cleanups) { + cleanup(this.#metadata); + } + } +} + +class ResourceConstructorImpl { + static create( + this: void, + metadata: M, + update: UpdateResource + ): ResourceConstructor { + return new ResourceConstructorImpl(update, metadata); + } + + readonly #metadata: M; + readonly #update: UpdateResource; + + constructor(update: UpdateResource, metadata: M) { + this.#metadata = metadata; + this.#update = update; + } + + create({ within }: { within: object }): ResourceInstance { + const state = ResourceState.create(this.#update, this.#metadata, within); + return ResourceInstance.create(state, within); + } + + use({ + within, + root, + }: { + within: object; + root: object; + }): ResourceInstance { + const state = ResourceState.scoped(this.#update, this.#metadata, { + owner: within, + root, + }); + return ResourceInstance.create(state, within); + } +} + +export const ResourceConstructor = ResourceConstructorImpl.create; +export type ResourceConstructor = ResourceConstructorImpl; + +type Assimilate = (value: T) => U; + +class ResourceInstance { + static create( + state: ResourceState, + root: object + ): ResourceInstance { + return new ResourceInstance( + state, + CachedFormula(() => state.nextRun()), + root + ); + } + + readonly #state: ResourceState; + readonly #instance: Reactive>; + readonly #root: object; + + private constructor( + state: ResourceState, + resourceInstance: Reactive>, + root: object + ) { + this.#state = state; + this.#instance = resourceInstance; + this.#root = root; + } + + adopt(parent: object): void { + this.#state.adopt(parent, { root: this.#root }); + } + + metadata(): Reactive { + return CachedFormula(() => this.#instance.current.value.metadata); + } + + instance(): Reactive; + instance(fn: Assimilate): Reactive; + instance(fn?: Assimilate): Reactive { + return CachedFormula(() => { + const instance = this.#instance.current.value.instance; + return fn ? fn(instance) : instance; + }); + } +} + +export function assimilateResource(value: T | Reactive): T { + if (isReactive(value)) { + return value.current; + } else { + return value; + } +} + +export function getRunInstance( + result: Reactive> +): T | undefined { + return result.current.value.instance; +} + +export function updateResource( + updater: UpdateResource +): UpdateResource { + return updater; +} + +type UpdateResource = (run: CreateResourceRun, metadata: M) => T; + +type RunResult = IteratorResult, ExposedFinalized>; + +function next(instance: T, metadata: M): RunResult { + return { + done: false, + value: { + instance, + metadata, + }, + }; +} + +function finalized( + instance: T, + metadata: M +): { done: true; value: ExposedFinalized } { + return { + done: true, + value: { + instance, + metadata, + }, + }; +} + +interface ExposedFinalized { + readonly instance: T; + readonly metadata: M; +} + +interface Exposed { + readonly instance: T; + readonly metadata: M; +} diff --git a/packages/universal/universal/src/reactive-core/resource/run.ts b/packages/universal/universal/src/reactive-core/resource/run.ts index e7194285..addcd302 100644 --- a/packages/universal/universal/src/reactive-core/resource/run.ts +++ b/packages/universal/universal/src/reactive-core/resource/run.ts @@ -2,7 +2,7 @@ import { Desc, type Description } from "@starbeam/debug"; import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; -import type { Handler, Resource, ResourceBlueprint } from "./resource"; +import type { Handler, Resource, ResourceBlueprint } from "./original-resource"; import type { ResourceState } from "./state.js"; /** diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts index ed4e4053..4329075b 100644 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ b/packages/universal/universal/src/reactive-core/resource/state.ts @@ -12,7 +12,7 @@ import { ResourceBlueprint, type ResourceFactory, type ResourceReturn, -} from "./resource"; +} from "./original-resource"; import { ResourceRun } from "./run"; /** diff --git a/packages/universal/universal/src/reactive-core/service.ts b/packages/universal/universal/src/reactive-core/service.ts index 7d7535b5..3074b85c 100644 --- a/packages/universal/universal/src/reactive-core/service.ts +++ b/packages/universal/universal/src/reactive-core/service.ts @@ -4,7 +4,7 @@ import { CONTEXT } from "@starbeam/runtime"; import { Factory, type IntoResource } from "./into.js"; import type { Blueprint } from "./reactive.js"; -import type { ResourceFactory } from "./resource/resource.js"; +import type { ResourceFactory } from "./resource/original-resource.js"; export function Service( create: Blueprint | ResourceFactory, diff --git a/packages/universal/universal/tests/hand-resource.spec.ts b/packages/universal/universal/tests/hand-resource.spec.ts index c3b83480..4a231f36 100644 --- a/packages/universal/universal/tests/hand-resource.spec.ts +++ b/packages/universal/universal/tests/hand-resource.spec.ts @@ -1,16 +1,31 @@ import "@starbeam/runtime"; import type { Reactive } from "@starbeam/interfaces"; -import { CachedFormula, Cell } from "@starbeam/reactive"; +import { CachedFormula, Cell, type FormulaFn } from "@starbeam/reactive"; import { LIFETIME } from "@starbeam/runtime"; +import { + assimilateResource, + getRunInstance, + ResourceConstructor, + ResourceState, + updateResource, +} from "@starbeam/universal"; import { describe, expect, test } from "vitest"; describe("A hand-rolled resource", () => { - test("works", () => { + test("based on formula", () => { const channelName = Cell("default"); const resourceOwner = {}; - function Channel(channelName: Reactive) { + function Channel(channelName: Reactive): { + resource: FormulaFn; + state: { + finalized: boolean; + cell: Cell; + channel: string | null; + counts: { init: number; cleanup: number }; + }; + } { const output = Cell(null as string | null); const state: { finalized: boolean; @@ -87,4 +102,260 @@ describe("A hand-rolled resource", () => { expect(state.counts.init).toBe(2); expect(state.finalized).toBe(true); }); + + test("using Resource runs", () => { + const channelName = Cell("default"); + const resourceOwner = {}; + + function Channel(channelName: Reactive): { + resource: FormulaFn; + state: TestState; + } { + const output = Cell(null as string | null); + + const update = updateResource< + TestInstance, + TestMetadata & { output: Cell } + >((run, metadata) => { + run.on.cleanup((metadata) => { + metadata.channel = null; + metadata.counts.cleanup++; + }); + + metadata.channel = channelName.current; + metadata.output.current = channelName.current.toUpperCase(); + metadata.counts.init++; + return metadata.output; + }); + + const state = ResourceState.create( + update, + { + counts: { init: 0, cleanup: 0 }, + output, + channel: null as null | string, + }, + resourceOwner + ); + + const formula = CachedFormula(() => { + return state.nextRun(); + }); + + const resource = CachedFormula(() => { + return getRunInstance(formula)?.current ?? null; + }); + return { resource, state }; + } + + const { resource: channel, state } = Channel(channelName); + const { metadata } = state; + + assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); + // make sure that polling the resource again doesn't change anything + assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); + + channelName.set("newname"); + assert({ channelName: "NEWNAME", cleanup: 1, init: 2, isFinalized: false }); + + LIFETIME.finalize(resourceOwner); + assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); + + console.log("setting channelName"); + channelName.set("newername"); + console.log("set channelName"); + assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); + + function assert({ + channelName, + cleanup, + init, + isFinalized, + }: { + channelName: string | null; + cleanup: number; + init: number; + isFinalized: boolean; + }): void { + expect(channel.current, "channel name").toBe(channelName); + expect(metadata.counts.cleanup, "cleanup count").toBe(cleanup); + expect(metadata.counts.init, "init count").toBe(init); + expect(state.isFinalized, "is finalized").toBe(isFinalized); + } + }); + + test("using ResourceConstructor", () => { + const channelName = Cell("default"); + const resourceOwner = {}; + + function Channel(channelName: Reactive): { + resource: Reactive; + metadata: TestMetadata; + } { + const metadata = { + counts: { init: 0, cleanup: 0 }, + channel: null as null | string, + } satisfies TestMetadata; + + const resource = ResourceConstructor(metadata, (run, metadata) => { + run.on.cleanup((metadata) => { + metadata.channel = null; + metadata.counts.cleanup++; + }); + + metadata.channel = channelName.current; + const instance = Cell( + channelName.current.toUpperCase(), + `instance${metadata.counts.init}` + ); + metadata.counts.init++; + + return instance; + }).create({ within: resourceOwner }); + + return { + resource: resource.instance(assimilateResource), + metadata, + }; + } + + const { resource: channel, metadata } = Channel(channelName); + + assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); + // make sure that polling the resource again doesn't change anything + assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); + + channelName.set("newname"); + assert({ channelName: "NEWNAME", cleanup: 1, init: 2, isFinalized: false }); + + LIFETIME.finalize(resourceOwner); + assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); + + channelName.set("newername"); + assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); + + function assert({ + channelName, + cleanup, + init, + }: { + channelName: string | undefined; + cleanup: number; + init: number; + isFinalized: boolean; + }): void { + expect(channel.current, "channel name").toBe(channelName); + expect(metadata.counts.cleanup, "cleanup count").toBe(cleanup); + expect(metadata.counts.init, "init count").toBe(init); + } + }); + + test("assimilating reactives", () => { + const lifetime = {}; + const resource = ResourceConstructor(null, () => { + return Cell(0); + }).create({ within: lifetime }); + + const instance = resource.instance((cell) => cell.current); + + expect(instance.current).toBe(0); + }); + + test("using a resource in a resource", () => { + const lifetime = {}; + const channelName = Cell("channel:default"); + const socketName = Cell("socket:default"); + + const Socket = ResourceConstructor({ instance: 0 }, ({ on }, meta) => { + meta.instance++; + const connection = { name: socketName.current, socket: "connected" }; + + on.cleanup(() => { + connection.socket = "disconnected"; + }); + + return connection; + }); + + const socketInstance = Socket.create({ + within: lifetime, + }); + + const Channel = ResourceConstructor( + { instance: 0, socket: socketInstance }, + ({ use }, meta) => { + meta.instance++; + const socketInstance = use(meta.socket); + const socket = socketInstance.instance(); + const socketMeta = socketInstance.metadata(); + const channel = `${socket.current.name}:${channelName.current}`; + + const connection = { + name: socketName.current, + messages: Cell(0, "messages"), + }; + + return { + channel, + get socketMeta() { + return socketMeta.current; + }, + get messages() { + return connection.messages.current; + }, + send: () => { + connection.messages.current++; + }, + }; + } + ); + + const channelInstance = Channel.create({ + within: lifetime, + }); + + const channel = channelInstance.instance(); + const meta = channelInstance.metadata(); + + expect(channel.current.messages).toBe(0); + expect(meta.current.instance).toBe(1); + expect(channel.current.socketMeta.instance).toBe(1); + + channelName.set("newname"); + expect(channel.current.messages).toBe(0); + expect(meta.current.instance).toBe(2); + expect(channel.current.socketMeta.instance).toBe(1); + }); + + test("assimilating resource constructors", () => { + const lifetime = {}; + const channelName = Cell("default"); + + const First = ResourceConstructor(null, () => { + // intentionally consume channelName in the constructor + const channel = Cell(channelName.current); + const counter = Cell(0); + + return { + get channel() { + return `${counter.current} ${channel.current}`; + }, + increment: () => { + counter.current++; + }, + }; + }); + + const resource = ResourceConstructor(null, () => First).create({ + within: lifetime, + }); + }); }); + +type TestState = ResourceState; +type TestInstance = Cell; + +interface TestMetadata { + channel: string | null; + counts: { init: number; cleanup: number }; +} diff --git a/packages/universal/universal/tests/resource.spec.ts b/packages/universal/universal/tests/resource.spec.ts index 19c83446..c9a1a93d 100644 --- a/packages/universal/universal/tests/resource.spec.ts +++ b/packages/universal/universal/tests/resource.spec.ts @@ -407,30 +407,6 @@ scenario("use(resource)", () => { verifyInvariants({ finalized: true }); }, ]; - - // expect(onTheFly1.current).toBe("on-the-fly-0: finalized"); - - // deps.counter.increment(); - // expect(outer.current).toBe("inner: active (run: 0, counter: 1)"); - - // deps.run.increment(); - // expect(outer.current).toBe("inner: active (run: 1, counter: 1)"); - - // deps.counter.increment(); - // deps.run.increment(); - // expect(outer.current).toBe("inner: active (run: 2, counter: 2)"); - - // // the inner resource is finalized regardless of how the outer resoruce is finalized. - // return [ - // () => { - // LIFETIME.finalize(owner); - // expect(outer.current).toBe("inner: finalized (run: 2, counter: 2)"); - // }, - // () => { - // LIFETIME.finalize(outer); - // expect(outer.current).toBe("inner: finalized (run: 2, counter: 2)"); - // }, - // ]; } ); From 92c4573f2b5831dc674e558e72e245a82268c9a1 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Wed, 29 Mar 2023 17:36:02 -0700 Subject: [PATCH 15/46] Third time's the charm! The third attempt to reimplement resource on top of the new primitives worked beautifully. It supports `ResourceList`, but where the previous implementation worked by implicitly adopting resources across runs, the new implementation of `ResourceList` manages the lifetimes of its child resources explicitly. The code is nearly as compact, in part because the new resource implementation is more honest about separating entire-resource state from per-run state. There's a bit of logic still left over supporting the adoption use-case, which I will remove soon, but even with this leftover code, the new resource implementation is still fairly compact. Reworking resources is the last part of the current PR, and this commit largely wraps up the design work on that. The main remaining piece of work is updating the React and Preact renderers, which should be straight forward. --- .vscode/settings.json | 9 +- package.json | 4 +- .../universal/debug/src/description/impl.ts | 1 + packages/universal/reactive/index.ts | 9 +- .../reactive/src/primitives/utils.ts | 10 +- packages/universal/reactive/src/utils.ts | 9 + .../universal/runtime/src/lifetime/api.ts | 2 +- packages/universal/tags/src/tag.ts | 8 + packages/universal/universal/index.ts | 12 +- .../reactive-core/resource/resource-core.ts | 285 ------------------ .../reactive-core/resource/v2/constructor.ts | 43 +++ .../src/reactive-core/resource/v2/index.ts | 9 + .../src/reactive-core/resource/v2/instance.ts | 49 +++ .../resource/v2/resource-core.ts | 26 ++ .../src/reactive-core/resource/v2/run.ts | 50 +++ .../src/reactive-core/resource/v2/state.ts | 122 ++++++++ .../src/reactive-core/resource/v2/types.ts | 23 ++ .../src/reactive-core/resource/v3/README.md | 164 ++++++++++ .../resource/v3/resource-list.ts | 102 +++++++ .../src/reactive-core/resource/v3/resource.ts | 201 ++++++++++++ .../universal/universal/tests/factory.spec.ts | 2 +- .../tests/higher-level/resource-list.spec.ts | 2 +- .../universal/tests/v3/resource-list.spec.ts | 206 +++++++++++++ .../universal/tests/v3/resource.spec.ts | 245 +++++++++++++++ 24 files changed, 1293 insertions(+), 300 deletions(-) delete mode 100644 packages/universal/universal/src/reactive-core/resource/resource-core.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/constructor.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/index.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/instance.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/run.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/state.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v2/types.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v3/README.md create mode 100644 packages/universal/universal/src/reactive-core/resource/v3/resource-list.ts create mode 100644 packages/universal/universal/src/reactive-core/resource/v3/resource.ts create mode 100644 packages/universal/universal/tests/v3/resource-list.spec.ts create mode 100644 packages/universal/universal/tests/v3/resource.spec.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index c405f48e..5e349907 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -69,11 +69,15 @@ } ], "npm-scripts.showStartNotification": false, + "rewrap.autoWrap.enabled": true, + "rewrap.reformat": true, + "rewrap.wrappingColumn": 80, "search.exclude": { "**/CHANGELOG.md": true, "pnpm-lock.yaml": true }, + "typescript.experimental.tsserver.web.enableProjectWideIntellisense": true, "typescript.preferences.importModuleSpecifier": "project-relative", "typescript.preferences.importModuleSpecifierEnding": "js", @@ -81,8 +85,5 @@ "typescript.tsserver.experimental.enableProjectDiagnostics": true, "vitest.enable": true, - "typescript.experimental.tsserver.web.enableProjectWideIntellisense": true, - "rewrap.autoWrap.enabled": true, - "rewrap.reformat": true, - "rewrap.wrappingColumn": 80 + "testing.automaticallyOpenPeekView": "never" } diff --git a/package.json b/package.json index 7edfcc96..86cc6c14 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "@types/node": "18.15.5", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", - "@vitest/ui": "^0.29.7", + "@vitest/ui": "^0.29.8", "eslint": "^8.36.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.8.0", @@ -140,7 +140,7 @@ "tslib": "^2.5.0", "typescript": "^5.0.2", "vite": "4.2.1", - "vitest": "0.29.7" + "vitest": "0.29.8" }, "license": "MIT", "nodemonConfig": { diff --git a/packages/universal/debug/src/description/impl.ts b/packages/universal/debug/src/description/impl.ts index dc3f45f1..86c7c946 100644 --- a/packages/universal/debug/src/description/impl.ts +++ b/packages/universal/debug/src/description/impl.ts @@ -571,6 +571,7 @@ if (import.meta.env.DEV) { readonly fromUser = undefined; readonly fullName = ""; + readonly name = ""; readonly id: interfaces.ReactiveId = "@starbeam:erased"; readonly internal = undefined; readonly parts: interfaces.DescriptionParts = { diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 31ac2694..4a0cb838 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -5,6 +5,11 @@ export { Formula } from "./src/primitives/formula.js"; export { FormulaLifecycle } from "./src/primitives/formula-lifecycle.js"; export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; -export { type FormulaFn } from "./src/primitives/utils.js"; +export { type FormulaFn, isFormulaFn } from "./src/primitives/utils.js"; export { defineRuntime, getRuntime } from "./src/runtime.js"; -export { intoReactive, isReactive, read } from "./src/utils.js"; +export { + intoReactive, + isReactive, + isTaggedReactive, + read, +} from "./src/utils.js"; diff --git a/packages/universal/reactive/src/primitives/utils.ts b/packages/universal/reactive/src/primitives/utils.ts index f9b2dc47..0fb52419 100644 --- a/packages/universal/reactive/src/primitives/utils.ts +++ b/packages/universal/reactive/src/primitives/utils.ts @@ -1,5 +1,5 @@ import type { Description } from "@starbeam/debug"; -import type { ReactiveValue, TaggedReactive } from "@starbeam/interfaces"; +import type { ReactiveValue, Tag, TaggedReactive } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import type { FormulaTag } from "@starbeam/tags"; @@ -36,6 +36,14 @@ export interface FormulaFn extends TaggedReactive { (): T; } +export function isFormulaFn(value: unknown): value is FormulaFn { + return !!( + typeof value === "function" && + TAG in value && + (value[TAG] as Tag).type === "formula" + ); +} + export function WrapFn(formula: ReactiveValue): FormulaFn { const fn = (): T => { return formula.read(RUNTIME.callerStack()); diff --git a/packages/universal/reactive/src/utils.ts b/packages/universal/reactive/src/utils.ts index e8539a95..429dc538 100644 --- a/packages/universal/reactive/src/utils.ts +++ b/packages/universal/reactive/src/utils.ts @@ -1,6 +1,7 @@ import type * as Debug from "@starbeam/debug"; import { callerStack, Desc } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; +import type { TagType } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { Static } from "./primitives/static.js"; @@ -25,6 +26,14 @@ export function isReactive( return is(value) && hasRead(value); } +export function isTaggedReactive( + this: void, + value: unknown, + tag: Type +): value is interfaces.TaggedReactive, T> { + return is(value) && value[TAG].type === tag && hasRead(value); +} + export function read( this: void, value: T | Reactive, diff --git a/packages/universal/runtime/src/lifetime/api.ts b/packages/universal/runtime/src/lifetime/api.ts index 038a7f17..d57ad97c 100644 --- a/packages/universal/runtime/src/lifetime/api.ts +++ b/packages/universal/runtime/src/lifetime/api.ts @@ -1,6 +1,6 @@ import { expected, isEqual, verify } from "@starbeam/verify"; -import { type Unsubscribe, ObjectLifetime } from "./object-lifetime.js"; +import { ObjectLifetime, type Unsubscribe } from "./object-lifetime.js"; /** * Implement this interface if you are building a new abstraction that wants to diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index 9587ed28..eb766bb2 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -163,6 +163,14 @@ export class FormulaTag extends Tag implements interfaces.FormulaTag { this.#tdz = tdz; } + [INSPECT]() { + return DisplayStruct("Formula", { + id: this.description.id, + initialized: !this.#tdz, + children: [...this.#children()], + }); + } + get tdz(): boolean { return this.#tdz; } diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 51dd3f5a..cfec33e9 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -30,17 +30,23 @@ export { type ResourceFactory, type ResourceReturn, } from "./src/reactive-core/resource/original-resource.js"; +export type { ResourceRun } from "./src/reactive-core/resource/run.js"; export { assimilateResource, CreateResourceRun, getRunInstance, ResourceConstructor, ResourceInstance, - ResourceMetadata, ResourceState, updateResource, -} from "./src/reactive-core/resource/resource-core.js"; -export type { ResourceRun } from "./src/reactive-core/resource/run.js"; +} from "./src/reactive-core/resource/v2/index.js"; +export { + Resource as Resource3, + type ResourceBlueprint as ResourceBlueprint3, + type ResourceRun as ResourceRun2, + use, +} from "./src/reactive-core/resource/v3/resource.js"; +export { ResourceList as ResourceList3 } from "./src/reactive-core/resource/v3/resource-list.js"; export { createService, reactiveService, diff --git a/packages/universal/universal/src/reactive-core/resource/resource-core.ts b/packages/universal/universal/src/reactive-core/resource/resource-core.ts deleted file mode 100644 index 0290a9fd..00000000 --- a/packages/universal/universal/src/reactive-core/resource/resource-core.ts +++ /dev/null @@ -1,285 +0,0 @@ -import type { Reactive, Unsubscribe } from "@starbeam/interfaces"; -import { CachedFormula, isReactive } from "@starbeam/reactive"; -import { LIFETIME } from "@starbeam/runtime"; -import { UNINITIALIZED } from "@starbeam/shared"; -import { isNotEqual, verified } from "@starbeam/verify"; - -type Cleanup = (metadata: M) => void; - -export class ResourceState { - static create( - update: UpdateResource, - metadata: M, - owner = {} - ): ResourceState { - const state = new ResourceState(update, metadata, owner); - LIFETIME.link(owner, state); - return state; - } - - static scoped( - update: UpdateResource, - metadata: M, - { owner, root }: { owner: object; root: object } - ): ResourceState { - const state = new ResourceState(update, metadata, owner); - LIFETIME.link(owner, state, { root }); - return state; - } - - /** - * The root lifetime of a resource is the lifetime of the top resource in a - * resource tree. Resources created within the root (via `use`) will be - * automatically adopted from one run to the next. - */ - #root: object; - #instance: T | UNINITIALIZED = UNINITIALIZED; - readonly #metadata: M; - readonly #update: UpdateResource; - #run: CreateResourceRun | null = null; - - /** - * Once the resource is finalized, its `nextRun` method will return - * `{done: true, metadata: metadata}`. - */ - #isFinalized = false; - - private constructor(update: UpdateResource, metadata: M, root: object) { - this.#update = update as UpdateResource; - this.#metadata = metadata; - this.#root = root; - - LIFETIME.on.cleanup(this, () => { - this.#isFinalized = true; - }); - } - - get #lastInstance(): T { - // The only way for this to happen is if the resource is finalized before it - // was ever consumed, and then it is consumed later. This should be avoided - // by construction, but there is still some work to do there. - return verified(this.#instance, isNotEqual(UNINITIALIZED)); - } - - adopt(parent: object, { root }: { root: object }): void { - LIFETIME.link(parent, this, { root }); - } - - nextRun(): RunResult { - if (this.#isFinalized) { - return finalized(this.#lastInstance, this.#metadata); - } - - const prevRun = this.#run; - - const run = this.#createRun(); - const result = next(this.#update(run, this.#metadata), this.#metadata); - this.#instance = result.value.instance; - - if (prevRun) LIFETIME.finalize(prevRun); - - return result; - } - - #createRun(): CreateResourceRun { - const run = (this.#run = CreateResourceRun.create( - this.#metadata, - this.#root - )); - LIFETIME.link(this, run); - return run; - } - - get isFinalized(): boolean { - return this.#isFinalized; - } - - get metadata(): M { - return this.#metadata; - } -} - -export class CreateResourceRun { - static create(metadata: M, root: object): CreateResourceRun { - return new CreateResourceRun(metadata, root); - } - - readonly #metadata: M; - readonly #root: object; - readonly #cleanups = new Set>(); - - private constructor(metadata: M, root: object) { - this.#metadata = metadata; - this.#root = root; - LIFETIME.on.cleanup(this, () => { - this.#cleanup(); - }); - } - - readonly on = { - cleanup: (fn: (metadata: M) => void): Unsubscribe => { - this.#cleanups.add(fn as Cleanup); - return () => this.#cleanups.delete(fn as Cleanup); - }, - }; - - use = ( - resource: ResourceConstructor | ResourceInstance - ): ResourceInstance => { - if (resource instanceof ResourceConstructorImpl) { - return resource.use({ within: this, root: this.#root }); - } else { - resource.adopt(this.#root); - return resource; - } - }; - - #cleanup(): void { - for (const cleanup of this.#cleanups) { - cleanup(this.#metadata); - } - } -} - -class ResourceConstructorImpl { - static create( - this: void, - metadata: M, - update: UpdateResource - ): ResourceConstructor { - return new ResourceConstructorImpl(update, metadata); - } - - readonly #metadata: M; - readonly #update: UpdateResource; - - constructor(update: UpdateResource, metadata: M) { - this.#metadata = metadata; - this.#update = update; - } - - create({ within }: { within: object }): ResourceInstance { - const state = ResourceState.create(this.#update, this.#metadata, within); - return ResourceInstance.create(state, within); - } - - use({ - within, - root, - }: { - within: object; - root: object; - }): ResourceInstance { - const state = ResourceState.scoped(this.#update, this.#metadata, { - owner: within, - root, - }); - return ResourceInstance.create(state, within); - } -} - -export const ResourceConstructor = ResourceConstructorImpl.create; -export type ResourceConstructor = ResourceConstructorImpl; - -type Assimilate = (value: T) => U; - -class ResourceInstance { - static create( - state: ResourceState, - root: object - ): ResourceInstance { - return new ResourceInstance( - state, - CachedFormula(() => state.nextRun()), - root - ); - } - - readonly #state: ResourceState; - readonly #instance: Reactive>; - readonly #root: object; - - private constructor( - state: ResourceState, - resourceInstance: Reactive>, - root: object - ) { - this.#state = state; - this.#instance = resourceInstance; - this.#root = root; - } - - adopt(parent: object): void { - this.#state.adopt(parent, { root: this.#root }); - } - - metadata(): Reactive { - return CachedFormula(() => this.#instance.current.value.metadata); - } - - instance(): Reactive; - instance(fn: Assimilate): Reactive; - instance(fn?: Assimilate): Reactive { - return CachedFormula(() => { - const instance = this.#instance.current.value.instance; - return fn ? fn(instance) : instance; - }); - } -} - -export function assimilateResource(value: T | Reactive): T { - if (isReactive(value)) { - return value.current; - } else { - return value; - } -} - -export function getRunInstance( - result: Reactive> -): T | undefined { - return result.current.value.instance; -} - -export function updateResource( - updater: UpdateResource -): UpdateResource { - return updater; -} - -type UpdateResource = (run: CreateResourceRun, metadata: M) => T; - -type RunResult = IteratorResult, ExposedFinalized>; - -function next(instance: T, metadata: M): RunResult { - return { - done: false, - value: { - instance, - metadata, - }, - }; -} - -function finalized( - instance: T, - metadata: M -): { done: true; value: ExposedFinalized } { - return { - done: true, - value: { - instance, - metadata, - }, - }; -} - -interface ExposedFinalized { - readonly instance: T; - readonly metadata: M; -} - -interface Exposed { - readonly instance: T; - readonly metadata: M; -} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/constructor.ts b/packages/universal/universal/src/reactive-core/resource/v2/constructor.ts new file mode 100644 index 00000000..00ed358b --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/constructor.ts @@ -0,0 +1,43 @@ +import { ResourceInstance } from "./instance.js"; +import { ResourceState } from "./state.js"; +import type { UpdateResource } from "./types.js"; + +export class ResourceConstructorImpl { + static create( + this: void, + metadata: M, + update: UpdateResource + ): ResourceConstructor { + return new ResourceConstructorImpl(update, metadata); + } + + readonly #metadata: M; + readonly #update: UpdateResource; + + constructor(update: UpdateResource, metadata: M) { + this.#metadata = metadata; + this.#update = update; + } + + create({ within }: { within: object }): ResourceInstance { + const state = ResourceState.create(this.#update, this.#metadata, within); + return ResourceInstance.create(state, within); + } + + use({ + within, + root, + }: { + within: object; + root: object; + }): ResourceInstance { + const state = ResourceState.scoped(this.#update, this.#metadata, { + owner: within, + root, + }); + return ResourceInstance.create(state, within); + } +} + +export type ResourceConstructor = ResourceConstructorImpl; +export const ResourceConstructor = ResourceConstructorImpl.create; diff --git a/packages/universal/universal/src/reactive-core/resource/v2/index.ts b/packages/universal/universal/src/reactive-core/resource/v2/index.ts new file mode 100644 index 00000000..029d5add --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/index.ts @@ -0,0 +1,9 @@ +export { ResourceConstructor } from "./constructor.js"; +export { ResourceInstance } from "./instance.js"; +export { + assimilateResource, + getRunInstance, + updateResource, +} from "./resource-core.js"; +export { CreateResourceRun } from "./run.js"; +export { ResourceState } from "./state.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/v2/instance.ts b/packages/universal/universal/src/reactive-core/resource/v2/instance.ts new file mode 100644 index 00000000..4caf0309 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/instance.ts @@ -0,0 +1,49 @@ +import type { Reactive } from "@starbeam/interfaces"; +import { CachedFormula } from "@starbeam/reactive"; + +import type { ResourceState } from "./state.js"; +import type { Assimilate, RunResult } from "./types.js"; + +export class ResourceInstance { + static create( + state: ResourceState, + root: object + ): ResourceInstance { + return new ResourceInstance( + state, + CachedFormula(() => state.nextRun()), + root + ); + } + + readonly #state: ResourceState; + readonly #instance: Reactive>; + readonly #root: object; + + private constructor( + state: ResourceState, + resourceInstance: Reactive>, + root: object + ) { + this.#state = state; + this.#instance = resourceInstance; + this.#root = root; + } + + adopt(parent: object): void { + this.#state.adopt(parent, { root: this.#root }); + } + + metadata(): Reactive { + return CachedFormula(() => this.#instance.current.value.metadata); + } + + instance(): Reactive; + instance(fn: Assimilate): Reactive; + instance(fn?: Assimilate): Reactive { + return CachedFormula(() => { + const instance = this.#instance.current.value.instance; + return fn ? fn(instance) : instance; + }); + } +} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts b/packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts new file mode 100644 index 00000000..e5d49973 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts @@ -0,0 +1,26 @@ +import type { Reactive } from "@starbeam/interfaces"; +import { isReactive } from "@starbeam/reactive"; + +import type { RunResult, UpdateResource } from "./types.js"; + +export type Cleanup = (metadata: M) => void; + +export function assimilateResource(value: T | Reactive): T { + if (isReactive(value)) { + return value.current; + } else { + return value; + } +} + +export function getRunInstance( + result: Reactive> +): T | undefined { + return result.current.value.instance; +} + +export function updateResource( + updater: UpdateResource +): UpdateResource { + return updater; +} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/run.ts b/packages/universal/universal/src/reactive-core/resource/v2/run.ts new file mode 100644 index 00000000..3ec885e6 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/run.ts @@ -0,0 +1,50 @@ +import type { Unsubscribe } from "@starbeam/interfaces"; +import { LIFETIME } from "@starbeam/runtime"; + +import { ResourceConstructorImpl } from "./constructor.js"; +import type { ResourceInstance } from "./instance.js"; +import type { ResourceConstructor } from "./types.js"; + +type Cleanup = (metadata: M) => void; + +export class CreateResourceRun { + static create(metadata: M, root: object): CreateResourceRun { + return new CreateResourceRun(metadata, root); + } + + readonly #metadata: M; + readonly #root: object; + readonly #cleanups = new Set>(); + + private constructor(metadata: M, root: object) { + this.#metadata = metadata; + this.#root = root; + LIFETIME.on.cleanup(this, () => { + this.#cleanup(); + }); + } + + readonly on = { + cleanup: (fn: (metadata: M) => void): Unsubscribe => { + this.#cleanups.add(fn as Cleanup); + return () => this.#cleanups.delete(fn as Cleanup); + }, + }; + + use = ( + resource: ResourceConstructor | ResourceInstance + ): ResourceInstance => { + if (resource instanceof ResourceConstructorImpl) { + return resource.use({ within: this, root: this.#root }); + } else { + resource.adopt(this.#root); + return resource; + } + }; + + #cleanup(): void { + for (const cleanup of this.#cleanups) { + cleanup(this.#metadata); + } + } +} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/state.ts b/packages/universal/universal/src/reactive-core/resource/v2/state.ts new file mode 100644 index 00000000..b278d93b --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/state.ts @@ -0,0 +1,122 @@ +import { LIFETIME } from "@starbeam/runtime"; +import { UNINITIALIZED } from "@starbeam/shared"; +import { isNotEqual, verified } from "@starbeam/verify"; + +import { CreateResourceRun } from "./run.js"; +import type { ExposedFinalized, RunResult, UpdateResource } from "./types.js"; + +export class ResourceState { + static create( + update: UpdateResource, + metadata: M, + owner = {} + ): ResourceState { + const state = new ResourceState(update, metadata, owner); + LIFETIME.link(owner, state); + return state; + } + + static scoped( + update: UpdateResource, + metadata: M, + { owner, root }: { owner: object; root: object } + ): ResourceState { + const state = new ResourceState(update, metadata, owner); + LIFETIME.link(owner, state, { root }); + return state; + } + + /** + * The root lifetime of a resource is the lifetime of the top resource in a + * resource tree. Resources created within the root (via `use`) will be + * automatically adopted from one run to the next. + */ + #root: object; + #instance: T | UNINITIALIZED = UNINITIALIZED; + readonly #metadata: M; + readonly #update: UpdateResource; + #run: CreateResourceRun | null = null; + + /** + * Once the resource is finalized, its `nextRun` method will return + * `{done: true, metadata: metadata}`. + */ + #isFinalized = false; + + private constructor(update: UpdateResource, metadata: M, root: object) { + this.#update = update as UpdateResource; + this.#metadata = metadata; + this.#root = root; + + LIFETIME.on.cleanup(this, () => { + this.#isFinalized = true; + }); + } + + get #lastInstance(): T { + // The only way for this to happen is if the resource is finalized before it + // was ever consumed, and then it is consumed later. This should be avoided + // by construction, but there is still some work to do there. + return verified(this.#instance, isNotEqual(UNINITIALIZED)); + } + + adopt(parent: object, { root }: { root: object }): void { + LIFETIME.link(parent, this, { root }); + } + + nextRun(): RunResult { + if (this.#isFinalized) { + return finalized(this.#lastInstance, this.#metadata); + } + + const prevRun = this.#run; + + const run = this.#createRun(); + const result = next(this.#update(run, this.#metadata), this.#metadata); + this.#instance = result.value.instance; + + if (prevRun) LIFETIME.finalize(prevRun); + + return result; + } + + #createRun(): CreateResourceRun { + const run = (this.#run = CreateResourceRun.create( + this.#metadata, + this.#root + )); + LIFETIME.link(this, run); + return run; + } + + get isFinalized(): boolean { + return this.#isFinalized; + } + + get metadata(): M { + return this.#metadata; + } +} + +function next(instance: T, metadata: M): RunResult { + return { + done: false, + value: { + instance, + metadata, + }, + }; +} + +function finalized( + instance: T, + metadata: M +): { done: true; value: ExposedFinalized } { + return { + done: true, + value: { + instance, + metadata, + }, + }; +} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/types.ts b/packages/universal/universal/src/reactive-core/resource/v2/types.ts new file mode 100644 index 00000000..7aa86967 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v2/types.ts @@ -0,0 +1,23 @@ +import type { CreateResourceRun } from "./run.js"; + +export type Cleanup = (metadata: M) => void; +export type UpdateResource = ( + run: CreateResourceRun, + metadata: M +) => T; +export type RunResult = IteratorResult< + Exposed, + ExposedFinalized +>; +export { ResourceConstructor } from "./constructor.js"; +export type Assimilate = (value: T) => U; + +export interface ExposedFinalized { + readonly instance: T; + readonly metadata: M; +} + +export interface Exposed { + readonly instance: T; + readonly metadata: M; +} diff --git a/packages/universal/universal/src/reactive-core/resource/v3/README.md b/packages/universal/universal/src/reactive-core/resource/v3/README.md new file mode 100644 index 00000000..d7592d28 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v3/README.md @@ -0,0 +1,164 @@ +# Resources + +At a basic level, resources are two-layer formulas: + +- A constructor formula that sets up the resource's instance (and registers + cleanup). The instance can (and usually does) have reactive state. +- An reactive instance that depends on the instance's state, and possibly other + reactive state. + +This design creates a distinction between construction and instance +dependencies, which is critical for making the resource work. + +```ts +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return Formula(() => { + return new Intl.DateTimeFormat().format(now.current); + }); +}); +``` + +In this case, the construction formula has no reactive dependencies, but the +instance formula depends on the `now` cell. + +Let's see what would happen if you tried to model this as a single formula: + +```ts +const now = Cell(Date.now()); +let timer: number; + +const Stopwatch = Formula(() => { + if (timer) clearInterval(timer); + + timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + return new Intl.DateTimeFormat().format(now.current); +}); +``` + +Since the code that sets up the interval and the code that uses it is inside the +same formula, the formula invalidates every time the interval ticks, and the +interval will be cleaned up and recreated on every tick. Definitely not what we +wanted! + +### Reactive Instance + +The second formula does not need to be a reactive value. For example, it could +be an instance of an object that stores a cell and exposes reactive getters: + +```ts +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return { + get now() { + return new Intl.DateTimeFormat().format(now.current); + }, + }; +}); +``` + +Instances of `Stopwatch` are methods with a reactive `now` property which will +change when the interval ticks. + +## Resource Runs + +A resource _instance_ is a long-lived reactive value that exists until the +resource is finalized. A resource instance has a number of _resource runs_ over +its lifetime. + +A resource is a reactive value that evaluates to its _current value_. + +### Evaluating the Constructor + +The steps for evaluating the constructor are: + +1. Evaluate the resource's constructor formula. Evaluating the formula: + + 1. Collects the run's reactive dependencies. + 2. Collects a list of the run's cleanup functions. + 3. Links any resources created within the run to the run's lifetime. If the + same resource instance was used in a previous run, this _adopts_ the + resource. + +2. Run finalizers for the previous resource run. + 1. Run its cleanup functions. + 2. Finalize any child resources that were not adopted by the new run. + +## Evaluating a Resource + +A resource's dependencies are the combination of: + +- The dependencies of the resource's instance formula. +- The dependencies of the current resource run (its constructor). + +This means that a resource will invalidate if its instance formula invalidates +_or_ if its constructor invalidates. + +Evaluating a resource: + +1. Validate the resource run. If the resource run is invalid, [evaluate the + constructor](#evaluating-the-constructor). +2. Evaluate the resource's instance formula. + +## Composing Resources + +The `use` method makes it possible for a resource to instantiate other +resources within the lifetime of the parent resource. + +There are several aspects of the design that make it easier to compose +resources. + +### Using a Resource Constructor + +```ts +const Channel = Resource(({ use }) => { + const socket = use(Socket); +}); +``` + +In this case, the Socket constructor is evaluated during `Channel`'s +constructor, and its instance is linked to the current run. Whenever the current +run is finalized, the Socket instance is finalized as well. + +### Reusing a Resource + +```ts +const socket = Socket.create({ within: owner }); + +const Channel = Resource(({ use }) => { + const socket = use(socket); +}); +``` + +In this case, `socket`'s lifetime is linked to the current run. Whenever the current +run is finalized, the Socket instance is finalized as well _unless_ it was +adopted by the next run. + +> `ResourceList` uses this feature to dynamically create child resources that are +> automatically cleaned up when they aren't used anymore. + +## Resource Metadata + +A resource can also have instance metadata that lasts for the entire lifetime of +the resource. This metadata can be used for state that persists across runs. diff --git a/packages/universal/universal/src/reactive-core/resource/v3/resource-list.ts b/packages/universal/universal/src/reactive-core/resource/v3/resource-list.ts new file mode 100644 index 00000000..9bece506 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v3/resource-list.ts @@ -0,0 +1,102 @@ +import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; +import { CachedFormula, Formula } from "@starbeam/reactive"; +import { LIFETIME } from "@starbeam/runtime"; + +import { Resource, type ResourceBlueprint } from "./resource.js"; + +export function ResourceList( + list: Iterable, + { + key, + map, + }: { + key: (item: T) => unknown; + map: (item: T) => ResourceBlueprint; + } +): ResourceBlueprint[]> { + const resources = new ResourceMap(); + + return Resource((_, { lifetime }) => { + const result: Resource[] = []; + const remaining = new Set(); + for (const item of list) { + const k = key(item); + remaining.add(k); + const resource = resources.get(k); + + if (resource) { + result.push(resource); + } else { + result.push(resources.create(k, map(item), lifetime)); + } + } + + resources.update(remaining); + + return result; + }); +} + +type InternalMap = Map; lifetime: object }>; + +class ResourceMap { + readonly #map: InternalMap = new Map(); + + get(key: unknown): Resource | undefined { + return this.#map.get(key)?.resource; + } + + create( + key: unknown, + resource: ResourceBlueprint, + parentLifetime: object + ): Resource { + const lifetime = {}; + LIFETIME.link(parentLifetime, lifetime); + const newResource = resource.create({ lifetime }); + this.#map.set(key, { resource: newResource, lifetime }); + return newResource; + } + + /** + * Finalize any resources from the previous run that aren't in the resource + * list anymore (based on their keys). + */ + update(remaining: Set): void { + for (const [key, { lifetime }] of this.#map) { + if (!remaining.has(key)) { + LIFETIME.finalize(lifetime); + this.#map.delete(key); + } + } + } +} + +export function FormulaList( + list: Iterable, + { + key, + map, + }: { + key: (item: T) => unknown; + map: (item: T) => U; + } +): Reactive { + const prev = new Map>(); + + return Formula(() => { + const result: U[] = []; + for (const item of list) { + const k = key(item); + const r = prev.get(k); + if (r) { + result.push(r.read()); + } else { + const newR = CachedFormula(() => map(item)); + result.push(newR.current); + prev.set(k, newR); + } + } + return result; + }); +} diff --git a/packages/universal/universal/src/reactive-core/resource/v3/resource.ts b/packages/universal/universal/src/reactive-core/resource/v3/resource.ts new file mode 100644 index 00000000..338f9955 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/resource/v3/resource.ts @@ -0,0 +1,201 @@ +import { DisplayStruct } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; +import { CachedFormula, type FormulaFn, isFormulaFn } from "@starbeam/reactive"; +import { LIFETIME, TAG } from "@starbeam/runtime"; + +export type UseResource = + | ResourceBlueprint + | (() => ResourceBlueprint) + | Resource; + +let id = 0; + +/** + * `ResourceRun` is passed in to the user-specified `ResourceConstructor` + * to create a new resource run. It's the lifetime of a single run of the + * resource, so finalizing a resource run finalizes anything that was created in + * its context (as long as it wasn't adopted by another run). + */ +export class ResourceRun { + readonly #state: ResourceState; + readonly id = id++; + + constructor(state: ResourceState) { + this.#state = state; + } + + on = { + /** + * on.cleanup happens once for each run of the resource. + */ + cleanup: (cleanup: ResourceCleanup): void => { + LIFETIME.on.cleanup(this, () => { + cleanup(this.#state.metadata); + }); + }, + + /** + * on.finalize happens when the resource's lifetime is finalized. This is + * primarily important for cleaning up state that persists across runs (such + * as in ResourceList). + */ + finalize: (cleanup: ResourceCleanup): void => { + LIFETIME.on.cleanup(this.#state.lifetime, () => { + cleanup(this.#state.metadata); + }); + }, + }; + + use = (( + resource: UseResource, + metadata?: unknown + ): FormulaFn => { + return use(resource, { metadata, root: this.#state.root, lifetime: this }); + }) as UseMethod; +} + +type UseMethod = ((resource: UseResource) => FormulaFn) & + ((resource: UseResource, metadata: M) => FormulaFn); + +export type Resource = FormulaFn; + +function useResource( + resource: Resource, + state: ResourceState +): Resource { + LIFETIME.link(state.lifetime, resource, { root: state.root }); + return resource; +} + +function useResourceConstructor( + resource: ResourceConstructor, + state: ResourceState +): Resource { + let last: ResourceRun | undefined; + const formula = CachedFormula(() => { + const next = new ResourceRun(state); + + LIFETIME.link(state.lifetime, next, { root: state.root }); + const instance = resource(next, { + metadata: state.metadata, + lifetime: state.lifetime, + }); + + // Finalize the previous run after running the new one to give the new one a + // chance to adopt resources from the previous run. + if (last !== undefined) LIFETIME.finalize(last); + last = next; + + return instance; + }); + + if (import.meta.env.DEV) { + Object.defineProperty(formula, Symbol.for("nodejs.util.inspect.custom"), { + configurable: true, + value: () => { + return DisplayStruct("Resource", { + tag: formula[TAG], + }); + }, + }); + } + + return formula; +} + +/** + * A blueprint is a reactive object that evaluates to the current + * resource run for a given resource constructor. + */ +export function use( + resource: UseResource, + state: ResourceState +): Resource { + if (isFormulaFn(resource)) { + return useResource(resource, state); + } else if (typeof resource === "function") { + return resource().use(state); + } else { + return resource.use(state); + } +} + +interface ResourceState { + /** + * A resource's metadata persists across runs of the resource. + */ + readonly metadata: M; + /** + * A resource's root is the root of the resource tree. It is used to adopt + * resources across runs. + */ + readonly root: object; + /** + * A resource's lifetime is the direct parent of the resource. The direct + * parent is contained inside the root. + */ + readonly lifetime: object; +} + +export interface ResourceBlueprint { + create: (( + this: ResourceBlueprint, + options: { + lifetime: object; + metadata?: undefined; + } + ) => Resource) & + ((options: { lifetime: object; metadata: M }) => Resource); + use: (options: { + lifetime: object; + metadata: M; + root: object; + }) => Resource; +} + +export function Resource( + resource: ResourceConstructor, + _description?: string | Description +): ResourceBlueprint { + return { + create: ({ lifetime, metadata }) => { + return useResourceConstructor(resource, { + lifetime, + root: lifetime, + metadata: metadata as M, + }); + }, + use: ({ + lifetime, + metadata, + root, + }: { + lifetime: object; + metadata: M; + root: object; + }) => { + return useResourceConstructor(resource, { + lifetime, + metadata, + root, + }); + }, + }; +} + +/** + * A resource constructor is a user-defined function that runs for each resource + * run. + */ +type ResourceConstructor = ( + run: ResourceRun, + /** + * The `resource` parameter provides information about the entire resource + * that persists across runs. It is useful when reusing state across runs. The + * `lifetime` property makes it possible to link state to the entire lifetime + * of the resource, which ensures that it it will get cleaned up, at the + * latest, when the resource itself is finalized. + */ + resource: { metadata: M; lifetime: object } +) => T; +type ResourceCleanup = (metadata: M) => void; diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.ts index d0dddc7d..c7442c38 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.ts @@ -2,7 +2,7 @@ import { entryPointFn } from "@starbeam/debug"; import { Static } from "@starbeam/reactive"; import { Frame } from "@starbeam/runtime"; import { describeTagged } from "@starbeam/tags"; -import { Cell, FormulaValidation, Reactive } from "@starbeam/universal"; +import { Cell, Reactive } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; describe("reactive Factory", () => { diff --git a/packages/universal/universal/tests/higher-level/resource-list.spec.ts b/packages/universal/universal/tests/higher-level/resource-list.spec.ts index f0d54943..607ab57c 100644 --- a/packages/universal/universal/tests/higher-level/resource-list.spec.ts +++ b/packages/universal/universal/tests/higher-level/resource-list.spec.ts @@ -1,9 +1,9 @@ import { DisplayStruct } from "@starbeam/debug"; import { reactive } from "@starbeam/js"; import { - type ResourceBlueprint, Formula, Resource, + type ResourceBlueprint, ResourceList, } from "@starbeam/universal"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; diff --git a/packages/universal/universal/tests/v3/resource-list.spec.ts b/packages/universal/universal/tests/v3/resource-list.spec.ts new file mode 100644 index 00000000..9aaadc24 --- /dev/null +++ b/packages/universal/universal/tests/v3/resource-list.spec.ts @@ -0,0 +1,206 @@ +import { DisplayStruct } from "@starbeam/debug"; +import { reactive } from "@starbeam/js"; +import { CachedFormula, Cell, type FormulaFn } from "@starbeam/reactive"; +import { + LIFETIME, + Resource3 as Resource, + type ResourceBlueprint3 as ResourceBlueprint, + ResourceList3 as ResourceList, +} from "@starbeam/universal"; +import { describe, expect, test } from "@starbeam-workspace/test-utils"; + +interface Item { + id: number; + name: string; + location: string; +} + +class Subscription { + #active = true; + declare readonly isActive: boolean; + + constructor(readonly name: string) { + Object.defineProperty(this, "isActive", { + enumerable: true, + get: () => { + return this.#active; + }, + }); + } + + [Symbol.for("nodejs.util.inspect.custom")](): object { + return DisplayStruct("Subscription", { + name: this.name, + isActive: this.isActive, + }); + } + + connect(): void { + this.#active = true; + } + + disconnect(): void { + this.#active = false; + } +} + +describe("v3::ResourceList", () => { + test("smoke test", () => { + const list: Item[] = reactive.array([ + { id: 1, name: "Tom", location: "NYC" }, + { id: 2, name: "Chirag", location: "NYC" }, + ]); + + const map = ( + item: Item + ): ResourceBlueprint<{ active: boolean; desc: string }> => { + const active = Cell(true); + return Resource(({ on }) => { + on.cleanup(() => { + active.set(false); + }); + + return { + get active() { + return active.current; + }, + get desc() { + return `${item.name} (${item.location})`; + }, + }; + }); + }; + + const lifetime = { lifetime: "root" }; + const mapped = ResourceList(list, { + key: (item) => item.id, + map, + }).create({ lifetime }); + + expect(mapped.current.map((r) => r.current)).toEqual([ + { active: true, desc: "Tom (NYC)" }, + { active: true, desc: "Chirag (NYC)" }, + ]); + + list.push({ id: 3, name: "John", location: "LA" }); + + expect(mapped.current.map((r) => r.current)).toEqual([ + { active: true, desc: "Tom (NYC)" }, + { active: true, desc: "Chirag (NYC)" }, + { active: true, desc: "John (LA)" }, + ]); + + LIFETIME.finalize(lifetime); + + expect(mapped.current.map((r) => r.current)).toEqual([ + { active: false, desc: "Tom (NYC)" }, + { active: false, desc: "Chirag (NYC)" }, + { active: false, desc: "John (LA)" }, + ]); + }); + + test("should update resources", () => { + const list: Item[] = reactive.array([ + { id: 1, name: "Tom", location: "NYC" }, + { id: 2, name: "Chirag", location: "NYC" }, + ]); + + const map = ( + item: Item + ): ResourceBlueprint< + FormulaFn<{ + card: string; + subscription: Subscription; + }> + > => + Resource(({ on }) => { + const subscription = new Subscription(item.name); + subscription.connect(); + + on.cleanup(() => { + console.trace({ disconnecting: item.id }); + subscription.disconnect(); + }); + + return CachedFormula(() => ({ + card: `${subscription.name} (${item.location})`, + subscription: subscription, + })); + }, `subscription for '${item.name}' (${item.id})`); + + const lifetime = { lifetime: "root" }; + + const linkables = ResourceList(list, { + key: (item) => item.id, + map, + }); + + const resources = linkables.create({ lifetime }); + + function current(): { card: string; subscription: Subscription }[] { + return resources.current.map((r) => r.current.current); + } + + expect(current()).toEqual([ + { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, + { + card: "Chirag (NYC)", + subscription: { name: "Chirag", isActive: true }, + }, + ]); + + list.push({ id: 3, name: "John", location: "NYC" }); + + let currentResources = current(); + + const tom = currentResources[0]?.subscription; + const chirag = currentResources[1]?.subscription; + const john = currentResources[2]?.subscription; + + expect(currentResources).toEqual([ + { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, + { + card: "Chirag (NYC)", + subscription: { name: "Chirag", isActive: true }, + }, + { card: "John (NYC)", subscription: { name: "John", isActive: true } }, + ]); + + list.pop(); + + expect(list).toEqual([ + { id: 1, name: "Tom", location: "NYC" }, + { id: 2, name: "Chirag", location: "NYC" }, + ]); + + expect(current()).toEqual([ + { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, + { + card: "Chirag (NYC)", + subscription: { name: "Chirag", isActive: true }, + }, + ]); + + expect(john?.isActive).toBe(false); + + list.reverse(); + + expect(list).toEqual([ + { id: 2, name: "Chirag", location: "NYC" }, + { id: 1, name: "Tom", location: "NYC" }, + ]); + + currentResources = resources.current.map((r) => r.current.current); + + expect(currentResources[0]?.subscription).toBe(chirag); + expect(currentResources[1]?.subscription).toBe(tom); + + expect(currentResources).toEqual([ + { + card: "Chirag (NYC)", + subscription: { name: "Chirag", isActive: true }, + }, + { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, + ]); + }); +}); diff --git a/packages/universal/universal/tests/v3/resource.spec.ts b/packages/universal/universal/tests/v3/resource.spec.ts new file mode 100644 index 00000000..938e60ac --- /dev/null +++ b/packages/universal/universal/tests/v3/resource.spec.ts @@ -0,0 +1,245 @@ +import { Marker } from "@starbeam/reactive"; +import { + Cell, + LIFETIME, + Resource3 as Resource, + type ResourceBlueprint3, +} from "@starbeam/universal"; +import { describe, expect, test } from "vitest"; + +describe("v3::resources", () => { + test("the basics", () => { + const testResource = new TestResource(); + const resource = testResource.instance; + + expect(resource.current.state).toEqual({ + count: 0, + init: 1, + finalized: 0, + }); + + testResource.invalidateConstructor(); + expect(resource.current.state).toEqual({ + count: 0, + init: 2, + finalized: 1, + }); + + resource.current.increment(); + expect(resource.current.state).toEqual({ + count: 1, + init: 2, + finalized: 1, + }); + + testResource.invalidateConstructor(); + expect(resource.current.state).toEqual({ + count: 0, + init: 3, + finalized: 2, + }); + + testResource.finalize(); + expect(resource.current.state).toEqual({ + count: 0, + init: 3, + finalized: 3, + }); + }); + + test("child resources", () => { + const name = Cell("default"); + let connectedCount = 0; + const Socket = Resource(({ on }) => { + const connected = { + socketName: name.current as string | null, + connected: ++connectedCount, + }; + + on.cleanup(() => { + connected.socketName = null; + }); + + return connected; + }); + + const Channel = Resource(({ use }) => { + const socket = use(Socket); + const messages = Cell(0); + + return { + get description() { + const { connected, socketName } = socket.current; + return `${ + socketName ?? "disconnected" + } (connected: ${connected}, messages: ${messages.current})`; + }, + get socket() { + return socket.current; + }, + get messages() { + return messages.current; + }, + send() { + messages.current++; + }, + }; + }); + + const lifetime = {}; + const channel = Channel.create({ lifetime }); + + expect(channel.current.description).toBe( + "default (connected: 1, messages: 0)" + ); + + channel.current.send(); + expect(channel.current.description).toBe( + "default (connected: 1, messages: 1)" + ); + + name.set("socketa"); + expect(channel.current.description).toBe( + "socketa (connected: 2, messages: 1)" + ); + }); + + test("adopting resources", () => { + const childResource = new TestResource(); + const child = childResource.instance; + + const invalidateParent = Marker(); + + const Parent = Resource( + ({ use }, { metadata: meta }: { metadata: { initHere: number } }) => { + const resource = use(child); + invalidateParent.read(); + meta.initHere++; + + return { + get state() { + return { + child: resource.current.state, + parent: { + init: meta.initHere, + }, + }; + }, + increment() { + resource.current.increment(); + }, + }; + } + ); + + const lifetime = {}; + const parent = Parent.create({ + lifetime, + metadata: { + initHere: 0, + }, + }); + + expect(parent.current.state).toEqual({ + parent: { + init: 1, + }, + child: { + count: 0, + init: 1, + finalized: 0, + }, + }); + + // invalidating the parent should not invalidate the child (it gets adopted + // by the new run). + invalidateParent.mark(); + + expect(parent.current.state).toEqual({ + parent: { + init: 2, + }, + child: { + count: 0, + init: 1, + finalized: 0, + }, + }); + + parent.current.increment(); + + expect(parent.current.state).toEqual({ + parent: { + init: 2, + }, + child: { + count: 1, + init: 1, + finalized: 0, + }, + }); + }); +}); + +interface TestInstance { + readonly state: { + readonly init: number; + readonly finalized: number; + readonly count: number; + }; + increment: () => void; +} + +class TestResource { + readonly #lifetime: object; + readonly #marker: Marker; + readonly #blueprint: ResourceBlueprint3; + readonly #instance: Resource; + + constructor() { + this.#lifetime = {}; + const marker = (this.#marker = Marker()); + const state = { + counts: { + init: 0, + finalized: 0, + }, + }; + + this.#blueprint = Resource(({ on }) => { + state.counts.init++; + + const cell = Cell(0); + marker.read(); + on.cleanup(() => { + state.counts.finalized++; + }); + + return { + get state() { + return { + ...state.counts, + count: cell.current, + }; + }, + increment() { + cell.current++; + }, + }; + }); + + this.#instance = this.#blueprint.create({ lifetime: this.#lifetime }); + } + + get instance(): Resource { + return this.#instance; + } + + invalidateConstructor(): void { + this.#marker.mark(); + } + + finalize(): void { + LIFETIME.finalize(this.#lifetime); + } +} From 24b04531732ed5e06795239a5e621a4a846f2010 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 31 Mar 2023 11:43:05 -0700 Subject: [PATCH 16/46] WIP @starbeam/resource --- package.json | 2 +- packages/universal/resource/.eslintrc.json | 12 + packages/universal/resource/.npmrc | 2 + packages/universal/resource/README.md | 164 + packages/universal/resource/index.ts | 3 + packages/universal/resource/package.json | 31 + packages/universal/resource/rollup.config.mjs | 3 + .../v3 => resource/src}/resource-list.ts | 0 .../resource/v3 => resource/src}/resource.ts | 0 .../universal/resource/tests/.eslintrc.json | 12 + packages/universal/resource/tests/.npmrc | 2 + .../universal/resource/tests/package.json | 20 + .../tests}/resource-list.spec.ts | 10 +- .../v3 => resource/tests}/resource.spec.ts | 12 +- .../universal/resource/tests/tsconfig.json | 13 + packages/universal/resource/tsconfig.json | 12 + packages/universal/universal/index.ts | 30 +- packages/universal/universal/package.json | 2 + .../src/reactive-core/resource/v3/README.md | 164 - .../universal/tests/hand-resource.spec.ts | 361 -- .../universal/universal/tests/package.json | 1 + pnpm-lock.yaml | 5396 +++++++++-------- 22 files changed, 3269 insertions(+), 2983 deletions(-) create mode 100644 packages/universal/resource/.eslintrc.json create mode 100644 packages/universal/resource/.npmrc create mode 100644 packages/universal/resource/README.md create mode 100644 packages/universal/resource/index.ts create mode 100644 packages/universal/resource/package.json create mode 100644 packages/universal/resource/rollup.config.mjs rename packages/universal/{universal/src/reactive-core/resource/v3 => resource/src}/resource-list.ts (100%) rename packages/universal/{universal/src/reactive-core/resource/v3 => resource/src}/resource.ts (100%) create mode 100644 packages/universal/resource/tests/.eslintrc.json create mode 100644 packages/universal/resource/tests/.npmrc create mode 100644 packages/universal/resource/tests/package.json rename packages/universal/{universal/tests/v3 => resource/tests}/resource-list.spec.ts (97%) rename packages/universal/{universal/tests/v3 => resource/tests}/resource.spec.ts (95%) create mode 100644 packages/universal/resource/tests/tsconfig.json create mode 100644 packages/universal/resource/tsconfig.json delete mode 100644 packages/universal/universal/tests/hand-resource.spec.ts diff --git a/package.json b/package.json index 86cc6c14..f5212f34 100644 --- a/package.json +++ b/package.json @@ -178,6 +178,6 @@ }, "volta": { "node": "19.8.1", - "pnpm": "7.30.3" + "pnpm": "8.1.0" } } diff --git a/packages/universal/resource/.eslintrc.json b/packages/universal/resource/.eslintrc.json new file mode 100644 index 00000000..6db04298 --- /dev/null +++ b/packages/universal/resource/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/commonjs"], + "files": ["index.ts", "src/**/*.ts"], + "parserOptions": { + "project": "packages/universal/resource/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/resource/.npmrc b/packages/universal/resource/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/resource/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/resource/README.md b/packages/universal/resource/README.md new file mode 100644 index 00000000..d7592d28 --- /dev/null +++ b/packages/universal/resource/README.md @@ -0,0 +1,164 @@ +# Resources + +At a basic level, resources are two-layer formulas: + +- A constructor formula that sets up the resource's instance (and registers + cleanup). The instance can (and usually does) have reactive state. +- An reactive instance that depends on the instance's state, and possibly other + reactive state. + +This design creates a distinction between construction and instance +dependencies, which is critical for making the resource work. + +```ts +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return Formula(() => { + return new Intl.DateTimeFormat().format(now.current); + }); +}); +``` + +In this case, the construction formula has no reactive dependencies, but the +instance formula depends on the `now` cell. + +Let's see what would happen if you tried to model this as a single formula: + +```ts +const now = Cell(Date.now()); +let timer: number; + +const Stopwatch = Formula(() => { + if (timer) clearInterval(timer); + + timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + return new Intl.DateTimeFormat().format(now.current); +}); +``` + +Since the code that sets up the interval and the code that uses it is inside the +same formula, the formula invalidates every time the interval ticks, and the +interval will be cleaned up and recreated on every tick. Definitely not what we +wanted! + +### Reactive Instance + +The second formula does not need to be a reactive value. For example, it could +be an instance of an object that stores a cell and exposes reactive getters: + +```ts +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return { + get now() { + return new Intl.DateTimeFormat().format(now.current); + }, + }; +}); +``` + +Instances of `Stopwatch` are methods with a reactive `now` property which will +change when the interval ticks. + +## Resource Runs + +A resource _instance_ is a long-lived reactive value that exists until the +resource is finalized. A resource instance has a number of _resource runs_ over +its lifetime. + +A resource is a reactive value that evaluates to its _current value_. + +### Evaluating the Constructor + +The steps for evaluating the constructor are: + +1. Evaluate the resource's constructor formula. Evaluating the formula: + + 1. Collects the run's reactive dependencies. + 2. Collects a list of the run's cleanup functions. + 3. Links any resources created within the run to the run's lifetime. If the + same resource instance was used in a previous run, this _adopts_ the + resource. + +2. Run finalizers for the previous resource run. + 1. Run its cleanup functions. + 2. Finalize any child resources that were not adopted by the new run. + +## Evaluating a Resource + +A resource's dependencies are the combination of: + +- The dependencies of the resource's instance formula. +- The dependencies of the current resource run (its constructor). + +This means that a resource will invalidate if its instance formula invalidates +_or_ if its constructor invalidates. + +Evaluating a resource: + +1. Validate the resource run. If the resource run is invalid, [evaluate the + constructor](#evaluating-the-constructor). +2. Evaluate the resource's instance formula. + +## Composing Resources + +The `use` method makes it possible for a resource to instantiate other +resources within the lifetime of the parent resource. + +There are several aspects of the design that make it easier to compose +resources. + +### Using a Resource Constructor + +```ts +const Channel = Resource(({ use }) => { + const socket = use(Socket); +}); +``` + +In this case, the Socket constructor is evaluated during `Channel`'s +constructor, and its instance is linked to the current run. Whenever the current +run is finalized, the Socket instance is finalized as well. + +### Reusing a Resource + +```ts +const socket = Socket.create({ within: owner }); + +const Channel = Resource(({ use }) => { + const socket = use(socket); +}); +``` + +In this case, `socket`'s lifetime is linked to the current run. Whenever the current +run is finalized, the Socket instance is finalized as well _unless_ it was +adopted by the next run. + +> `ResourceList` uses this feature to dynamically create child resources that are +> automatically cleaned up when they aren't used anymore. + +## Resource Metadata + +A resource can also have instance metadata that lasts for the entire lifetime of +the resource. This metadata can be used for state that persists across runs. diff --git a/packages/universal/resource/index.ts b/packages/universal/resource/index.ts new file mode 100644 index 00000000..760576d1 --- /dev/null +++ b/packages/universal/resource/index.ts @@ -0,0 +1,3 @@ +export type { ResourceBlueprint, UseResource } from "./src/resource.js"; +export { Resource, ResourceRun, use } from "./src/resource.js"; +export { FormulaList, ResourceList } from "./src/resource-list.js"; diff --git a/packages/universal/resource/package.json b/packages/universal/resource/package.json new file mode 100644 index 00000000..d66bea69 --- /dev/null +++ b/packages/universal/resource/package.json @@ -0,0 +1,31 @@ +{ + "name": "@starbeam/resource", + "types": "index.ts", + "publishConfig": { + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.cjs" + } + }, + "main": "dist/index.cjs", + "types": "dist/index.d.ts" + }, + "starbeam:type": "library:public", + "scripts": { + "test:specs": "vitest --run", + "test:types": "tsc -b" + }, + "dependencies": { + "@starbeam/core-utils": "workspace:^", + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", + "@starbeam/runtime": "workspace:^", + "@starbeam/shared": "workspace:^" + }, + "devDependencies": { + "@starbeam-dev/build-support": "workspace:*" + } +} diff --git a/packages/universal/resource/rollup.config.mjs b/packages/universal/resource/rollup.config.mjs new file mode 100644 index 00000000..dc01dc49 --- /dev/null +++ b/packages/universal/resource/rollup.config.mjs @@ -0,0 +1,3 @@ +import { Package } from "@starbeam-dev/build-support"; + +export default Package.config(import.meta); diff --git a/packages/universal/universal/src/reactive-core/resource/v3/resource-list.ts b/packages/universal/resource/src/resource-list.ts similarity index 100% rename from packages/universal/universal/src/reactive-core/resource/v3/resource-list.ts rename to packages/universal/resource/src/resource-list.ts diff --git a/packages/universal/universal/src/reactive-core/resource/v3/resource.ts b/packages/universal/resource/src/resource.ts similarity index 100% rename from packages/universal/universal/src/reactive-core/resource/v3/resource.ts rename to packages/universal/resource/src/resource.ts diff --git a/packages/universal/resource/tests/.eslintrc.json b/packages/universal/resource/tests/.eslintrc.json new file mode 100644 index 00000000..bef288a8 --- /dev/null +++ b/packages/universal/resource/tests/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/loose"], + "files": ["**/*.ts"], + "parserOptions": { + "project": "packages/universal/resource/tests/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/resource/tests/.npmrc b/packages/universal/resource/tests/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/resource/tests/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/resource/tests/package.json b/packages/universal/resource/tests/package.json new file mode 100644 index 00000000..122e8439 --- /dev/null +++ b/packages/universal/resource/tests/package.json @@ -0,0 +1,20 @@ +{ + "private": true, + "name": "@starbeam-tests/resource", + "version": "1.0.0", + "type": "module", + "starbeam:type": "tests", + "scripts": { + "test:lint": "eslint" + }, + "dependencies": { + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/js": "workspace:^", + "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", + "@starbeam/runtime": "workspace:^", + "@starbeam/shared": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^" + } +} diff --git a/packages/universal/universal/tests/v3/resource-list.spec.ts b/packages/universal/resource/tests/resource-list.spec.ts similarity index 97% rename from packages/universal/universal/tests/v3/resource-list.spec.ts rename to packages/universal/resource/tests/resource-list.spec.ts index 9aaadc24..b7201972 100644 --- a/packages/universal/universal/tests/v3/resource-list.spec.ts +++ b/packages/universal/resource/tests/resource-list.spec.ts @@ -2,11 +2,11 @@ import { DisplayStruct } from "@starbeam/debug"; import { reactive } from "@starbeam/js"; import { CachedFormula, Cell, type FormulaFn } from "@starbeam/reactive"; import { - LIFETIME, - Resource3 as Resource, - type ResourceBlueprint3 as ResourceBlueprint, - ResourceList3 as ResourceList, -} from "@starbeam/universal"; + Resource, + type ResourceBlueprint, + ResourceList, +} from "@starbeam/resource"; +import { LIFETIME } from "@starbeam/runtime"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; interface Item { diff --git a/packages/universal/universal/tests/v3/resource.spec.ts b/packages/universal/resource/tests/resource.spec.ts similarity index 95% rename from packages/universal/universal/tests/v3/resource.spec.ts rename to packages/universal/resource/tests/resource.spec.ts index 938e60ac..68d097eb 100644 --- a/packages/universal/universal/tests/v3/resource.spec.ts +++ b/packages/universal/resource/tests/resource.spec.ts @@ -1,10 +1,6 @@ -import { Marker } from "@starbeam/reactive"; -import { - Cell, - LIFETIME, - Resource3 as Resource, - type ResourceBlueprint3, -} from "@starbeam/universal"; +import { Cell, Marker } from "@starbeam/reactive"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; +import { LIFETIME } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; describe("v3::resources", () => { @@ -193,7 +189,7 @@ interface TestInstance { class TestResource { readonly #lifetime: object; readonly #marker: Marker; - readonly #blueprint: ResourceBlueprint3; + readonly #blueprint: ResourceBlueprint; readonly #instance: Resource; constructor() { diff --git a/packages/universal/resource/tests/tsconfig.json b/packages/universal/resource/tests/tsconfig.json new file mode 100644 index 00000000..28a12c31 --- /dev/null +++ b/packages/universal/resource/tests/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../../dist/types", + "declarationMap": true, + "outDir": "../../../../dist/packages", + "types": ["../../../env"] + }, + "exclude": ["dist/**/*"], + "include": ["**/*.ts"] +} diff --git a/packages/universal/resource/tsconfig.json b/packages/universal/resource/tsconfig.json new file mode 100644 index 00000000..4790a1ab --- /dev/null +++ b/packages/universal/resource/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../dist/types", + "declarationMap": true, + "outDir": "../../../dist/packages", + "types": ["../../env"] + }, + "exclude": ["dist/**/*"] +} diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index cfec33e9..7e4e473c 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -24,29 +24,6 @@ export type { ReactiveFactory, } from "./src/reactive-core/reactive.js"; export { Reactive } from "./src/reactive-core/reactive.js"; -export { - Resource, - type ResourceBlueprint, - type ResourceFactory, - type ResourceReturn, -} from "./src/reactive-core/resource/original-resource.js"; -export type { ResourceRun } from "./src/reactive-core/resource/run.js"; -export { - assimilateResource, - CreateResourceRun, - getRunInstance, - ResourceConstructor, - ResourceInstance, - ResourceState, - updateResource, -} from "./src/reactive-core/resource/v2/index.js"; -export { - Resource as Resource3, - type ResourceBlueprint as ResourceBlueprint3, - type ResourceRun as ResourceRun2, - use, -} from "./src/reactive-core/resource/v3/resource.js"; -export { ResourceList as ResourceList3 } from "./src/reactive-core/resource/v3/resource-list.js"; export { createService, reactiveService, @@ -68,4 +45,11 @@ export { Formula as PolledFormula, Static, } from "@starbeam/reactive"; +export { + Resource, + type ResourceBlueprint, + type ResourceRun, + use, +} from "@starbeam/resource"; +export { ResourceList as ResourceList3 } from "@starbeam/resource/src/resource-list.js"; export { LIFETIME, PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; diff --git a/packages/universal/universal/package.json b/packages/universal/universal/package.json index af576f4c..0b198f6f 100644 --- a/packages/universal/universal/package.json +++ b/packages/universal/universal/package.json @@ -29,9 +29,11 @@ "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", + "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" }, "devDependencies": { diff --git a/packages/universal/universal/src/reactive-core/resource/v3/README.md b/packages/universal/universal/src/reactive-core/resource/v3/README.md index d7592d28..e69de29b 100644 --- a/packages/universal/universal/src/reactive-core/resource/v3/README.md +++ b/packages/universal/universal/src/reactive-core/resource/v3/README.md @@ -1,164 +0,0 @@ -# Resources - -At a basic level, resources are two-layer formulas: - -- A constructor formula that sets up the resource's instance (and registers - cleanup). The instance can (and usually does) have reactive state. -- An reactive instance that depends on the instance's state, and possibly other - reactive state. - -This design creates a distinction between construction and instance -dependencies, which is critical for making the resource work. - -```ts -const Stopwatch = Resource(({ on }) => { - const now = Cell(Date.now()); - - const timer = setInterval(() => { - now.set(Date.now()); - }, 1000); - - on.cleanup(() => { - clearInterval(timer); - }); - - return Formula(() => { - return new Intl.DateTimeFormat().format(now.current); - }); -}); -``` - -In this case, the construction formula has no reactive dependencies, but the -instance formula depends on the `now` cell. - -Let's see what would happen if you tried to model this as a single formula: - -```ts -const now = Cell(Date.now()); -let timer: number; - -const Stopwatch = Formula(() => { - if (timer) clearInterval(timer); - - timer = setInterval(() => { - now.set(Date.now()); - }, 1000); - - return new Intl.DateTimeFormat().format(now.current); -}); -``` - -Since the code that sets up the interval and the code that uses it is inside the -same formula, the formula invalidates every time the interval ticks, and the -interval will be cleaned up and recreated on every tick. Definitely not what we -wanted! - -### Reactive Instance - -The second formula does not need to be a reactive value. For example, it could -be an instance of an object that stores a cell and exposes reactive getters: - -```ts -const Stopwatch = Resource(({ on }) => { - const now = Cell(Date.now()); - - const timer = setInterval(() => { - now.set(Date.now()); - }, 1000); - - on.cleanup(() => { - clearInterval(timer); - }); - - return { - get now() { - return new Intl.DateTimeFormat().format(now.current); - }, - }; -}); -``` - -Instances of `Stopwatch` are methods with a reactive `now` property which will -change when the interval ticks. - -## Resource Runs - -A resource _instance_ is a long-lived reactive value that exists until the -resource is finalized. A resource instance has a number of _resource runs_ over -its lifetime. - -A resource is a reactive value that evaluates to its _current value_. - -### Evaluating the Constructor - -The steps for evaluating the constructor are: - -1. Evaluate the resource's constructor formula. Evaluating the formula: - - 1. Collects the run's reactive dependencies. - 2. Collects a list of the run's cleanup functions. - 3. Links any resources created within the run to the run's lifetime. If the - same resource instance was used in a previous run, this _adopts_ the - resource. - -2. Run finalizers for the previous resource run. - 1. Run its cleanup functions. - 2. Finalize any child resources that were not adopted by the new run. - -## Evaluating a Resource - -A resource's dependencies are the combination of: - -- The dependencies of the resource's instance formula. -- The dependencies of the current resource run (its constructor). - -This means that a resource will invalidate if its instance formula invalidates -_or_ if its constructor invalidates. - -Evaluating a resource: - -1. Validate the resource run. If the resource run is invalid, [evaluate the - constructor](#evaluating-the-constructor). -2. Evaluate the resource's instance formula. - -## Composing Resources - -The `use` method makes it possible for a resource to instantiate other -resources within the lifetime of the parent resource. - -There are several aspects of the design that make it easier to compose -resources. - -### Using a Resource Constructor - -```ts -const Channel = Resource(({ use }) => { - const socket = use(Socket); -}); -``` - -In this case, the Socket constructor is evaluated during `Channel`'s -constructor, and its instance is linked to the current run. Whenever the current -run is finalized, the Socket instance is finalized as well. - -### Reusing a Resource - -```ts -const socket = Socket.create({ within: owner }); - -const Channel = Resource(({ use }) => { - const socket = use(socket); -}); -``` - -In this case, `socket`'s lifetime is linked to the current run. Whenever the current -run is finalized, the Socket instance is finalized as well _unless_ it was -adopted by the next run. - -> `ResourceList` uses this feature to dynamically create child resources that are -> automatically cleaned up when they aren't used anymore. - -## Resource Metadata - -A resource can also have instance metadata that lasts for the entire lifetime of -the resource. This metadata can be used for state that persists across runs. diff --git a/packages/universal/universal/tests/hand-resource.spec.ts b/packages/universal/universal/tests/hand-resource.spec.ts deleted file mode 100644 index 4a231f36..00000000 --- a/packages/universal/universal/tests/hand-resource.spec.ts +++ /dev/null @@ -1,361 +0,0 @@ -import "@starbeam/runtime"; - -import type { Reactive } from "@starbeam/interfaces"; -import { CachedFormula, Cell, type FormulaFn } from "@starbeam/reactive"; -import { LIFETIME } from "@starbeam/runtime"; -import { - assimilateResource, - getRunInstance, - ResourceConstructor, - ResourceState, - updateResource, -} from "@starbeam/universal"; -import { describe, expect, test } from "vitest"; - -describe("A hand-rolled resource", () => { - test("based on formula", () => { - const channelName = Cell("default"); - const resourceOwner = {}; - - function Channel(channelName: Reactive): { - resource: FormulaFn; - state: { - finalized: boolean; - cell: Cell; - channel: string | null; - counts: { init: number; cleanup: number }; - }; - } { - const output = Cell(null as string | null); - const state: { - finalized: boolean; - cell: Cell; - channel: string | null; - counts: { init: number; cleanup: number }; - } = { - finalized: false, - cell: output, - channel: null, - counts: { init: 0, cleanup: 0 }, - }; - - function cleanup(): void { - state.channel = null; - state.counts.cleanup++; - state.cell.current = null; - } - - const formula = CachedFormula(() => { - if (state.channel) { - cleanup(); - } - - if (state.counts.init === 0) { - LIFETIME.on.cleanup(resourceOwner, () => { - cleanup(); - state.finalized = true; - }); - } - - if (!state.finalized) { - state.channel = channelName.current; - state.cell.current = channelName.current.toUpperCase(); - state.counts.init++; - } - - return state.cell; - }); - - const resource = CachedFormula(() => { - return formula.current.current; - }); - return { resource, state }; - } - - const { resource: channel, state } = Channel(channelName); - - expect(channel.current).toBe("DEFAULT"); - expect(state.counts.cleanup).toBe(0); - expect(state.counts.init).toBe(1); - expect(state.finalized).toBe(false); - - expect(channel.current).toBe("DEFAULT"); - expect(state.counts.cleanup).toBe(0); - expect(state.counts.init).toBe(1); - expect(state.finalized).toBe(false); - - channelName.set("newname"); - expect(channel.current).toBe("NEWNAME"); - expect(state.counts.cleanup).toBe(1); - expect(state.counts.init).toBe(2); - expect(state.finalized).toBe(false); - - LIFETIME.finalize(resourceOwner); - expect(channel.current).toBe(null); - expect(state.counts.cleanup).toBe(2); - expect(state.counts.init).toBe(2); - expect(state.finalized).toBe(true); - - channelName.set("newername"); - expect(channel.current).toBe(null); - expect(state.counts.cleanup).toBe(2); - expect(state.counts.init).toBe(2); - expect(state.finalized).toBe(true); - }); - - test("using Resource runs", () => { - const channelName = Cell("default"); - const resourceOwner = {}; - - function Channel(channelName: Reactive): { - resource: FormulaFn; - state: TestState; - } { - const output = Cell(null as string | null); - - const update = updateResource< - TestInstance, - TestMetadata & { output: Cell } - >((run, metadata) => { - run.on.cleanup((metadata) => { - metadata.channel = null; - metadata.counts.cleanup++; - }); - - metadata.channel = channelName.current; - metadata.output.current = channelName.current.toUpperCase(); - metadata.counts.init++; - return metadata.output; - }); - - const state = ResourceState.create( - update, - { - counts: { init: 0, cleanup: 0 }, - output, - channel: null as null | string, - }, - resourceOwner - ); - - const formula = CachedFormula(() => { - return state.nextRun(); - }); - - const resource = CachedFormula(() => { - return getRunInstance(formula)?.current ?? null; - }); - return { resource, state }; - } - - const { resource: channel, state } = Channel(channelName); - const { metadata } = state; - - assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); - // make sure that polling the resource again doesn't change anything - assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); - - channelName.set("newname"); - assert({ channelName: "NEWNAME", cleanup: 1, init: 2, isFinalized: false }); - - LIFETIME.finalize(resourceOwner); - assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); - - console.log("setting channelName"); - channelName.set("newername"); - console.log("set channelName"); - assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); - - function assert({ - channelName, - cleanup, - init, - isFinalized, - }: { - channelName: string | null; - cleanup: number; - init: number; - isFinalized: boolean; - }): void { - expect(channel.current, "channel name").toBe(channelName); - expect(metadata.counts.cleanup, "cleanup count").toBe(cleanup); - expect(metadata.counts.init, "init count").toBe(init); - expect(state.isFinalized, "is finalized").toBe(isFinalized); - } - }); - - test("using ResourceConstructor", () => { - const channelName = Cell("default"); - const resourceOwner = {}; - - function Channel(channelName: Reactive): { - resource: Reactive; - metadata: TestMetadata; - } { - const metadata = { - counts: { init: 0, cleanup: 0 }, - channel: null as null | string, - } satisfies TestMetadata; - - const resource = ResourceConstructor(metadata, (run, metadata) => { - run.on.cleanup((metadata) => { - metadata.channel = null; - metadata.counts.cleanup++; - }); - - metadata.channel = channelName.current; - const instance = Cell( - channelName.current.toUpperCase(), - `instance${metadata.counts.init}` - ); - metadata.counts.init++; - - return instance; - }).create({ within: resourceOwner }); - - return { - resource: resource.instance(assimilateResource), - metadata, - }; - } - - const { resource: channel, metadata } = Channel(channelName); - - assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); - // make sure that polling the resource again doesn't change anything - assert({ channelName: "DEFAULT", cleanup: 0, init: 1, isFinalized: false }); - - channelName.set("newname"); - assert({ channelName: "NEWNAME", cleanup: 1, init: 2, isFinalized: false }); - - LIFETIME.finalize(resourceOwner); - assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); - - channelName.set("newername"); - assert({ channelName: "NEWNAME", cleanup: 2, init: 2, isFinalized: true }); - - function assert({ - channelName, - cleanup, - init, - }: { - channelName: string | undefined; - cleanup: number; - init: number; - isFinalized: boolean; - }): void { - expect(channel.current, "channel name").toBe(channelName); - expect(metadata.counts.cleanup, "cleanup count").toBe(cleanup); - expect(metadata.counts.init, "init count").toBe(init); - } - }); - - test("assimilating reactives", () => { - const lifetime = {}; - const resource = ResourceConstructor(null, () => { - return Cell(0); - }).create({ within: lifetime }); - - const instance = resource.instance((cell) => cell.current); - - expect(instance.current).toBe(0); - }); - - test("using a resource in a resource", () => { - const lifetime = {}; - const channelName = Cell("channel:default"); - const socketName = Cell("socket:default"); - - const Socket = ResourceConstructor({ instance: 0 }, ({ on }, meta) => { - meta.instance++; - const connection = { name: socketName.current, socket: "connected" }; - - on.cleanup(() => { - connection.socket = "disconnected"; - }); - - return connection; - }); - - const socketInstance = Socket.create({ - within: lifetime, - }); - - const Channel = ResourceConstructor( - { instance: 0, socket: socketInstance }, - ({ use }, meta) => { - meta.instance++; - const socketInstance = use(meta.socket); - const socket = socketInstance.instance(); - const socketMeta = socketInstance.metadata(); - const channel = `${socket.current.name}:${channelName.current}`; - - const connection = { - name: socketName.current, - messages: Cell(0, "messages"), - }; - - return { - channel, - get socketMeta() { - return socketMeta.current; - }, - get messages() { - return connection.messages.current; - }, - send: () => { - connection.messages.current++; - }, - }; - } - ); - - const channelInstance = Channel.create({ - within: lifetime, - }); - - const channel = channelInstance.instance(); - const meta = channelInstance.metadata(); - - expect(channel.current.messages).toBe(0); - expect(meta.current.instance).toBe(1); - expect(channel.current.socketMeta.instance).toBe(1); - - channelName.set("newname"); - expect(channel.current.messages).toBe(0); - expect(meta.current.instance).toBe(2); - expect(channel.current.socketMeta.instance).toBe(1); - }); - - test("assimilating resource constructors", () => { - const lifetime = {}; - const channelName = Cell("default"); - - const First = ResourceConstructor(null, () => { - // intentionally consume channelName in the constructor - const channel = Cell(channelName.current); - const counter = Cell(0); - - return { - get channel() { - return `${counter.current} ${channel.current}`; - }, - increment: () => { - counter.current++; - }, - }; - }); - - const resource = ResourceConstructor(null, () => First).create({ - within: lifetime, - }); - }); -}); - -type TestState = ResourceState; -type TestInstance = Cell; - -interface TestMetadata { - channel: string | null; - counts: { init: number; cleanup: number }; -} diff --git a/packages/universal/universal/tests/package.json b/packages/universal/universal/tests/package.json index fd2cd854..663b1d77 100644 --- a/packages/universal/universal/tests/package.json +++ b/packages/universal/universal/tests/package.json @@ -11,6 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/js": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41fd59a6..a4bce8e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: 5.4 +lockfileVersion: '6.0' overrides: '@rollup/plugin-commonjs': ^24.0.0 @@ -18,1335 +18,1832 @@ overrides: importers: .: - specifiers: - '@babel/eslint-parser': ^7.21.3 - '@babel/plugin-proposal-decorators': ^7.21.0 - '@babel/plugin-syntax-dynamic-import': ^7.8.3 - '@babel/plugin-transform-runtime': ^7.21.0 - '@babel/preset-env': ^7.20.2 - '@babel/preset-react': ^7.18.6 - '@babel/preset-typescript': ^7.21.0 - '@babel/runtime': ^7.21.0 - '@changesets/changelog-git': ^0.1.14 - '@changesets/cli': ^2.26.1 - '@changesets/config': ^2.3.0 - '@starbeam-dev/build-support': workspace:1.0.0 - '@starbeam/core-utils': workspace:^0.8.9 - '@starbeam/eslint-plugin': workspace:^1.0.0 - '@types/eslint': ^8.21.3 - '@types/node': 18.15.5 - '@typescript-eslint/eslint-plugin': ^5.56.0 - '@typescript-eslint/parser': ^5.56.0 - '@vitest/ui': ^0.29.7 - eslint: ^8.36.0 - eslint-config-airbnb: ^19.0.4 - eslint-config-prettier: ^8.8.0 - eslint-import-resolver-typescript: ^3.5.3 - eslint-plugin-import: ^2.27.5 - eslint-plugin-jsonc: ^2.7.0 - eslint-plugin-prettier: ^4.2.1 - eslint-plugin-simple-import-sort: ^10.0.0 - eslint-plugin-unused-imports: ^2.0.0 - esno: ^0.16.3 - fast-glob: ^3.2.12 - happy-dom: ^8.9.0 - jsdom: ^21.1.1 - prettier: ^2.8.6 - tslib: ^2.5.0 - typescript: ^5.0.2 - vite: 4.2.1 - vitest: 0.29.7 dependencies: - '@starbeam/core-utils': link:packages/universal/core-utils + '@starbeam/core-utils': + specifier: workspace:^0.8.9 + version: link:packages/universal/core-utils devDependencies: - '@babel/eslint-parser': 7.21.3_pxuto7xgangxlusvzceggvrmde - '@babel/plugin-proposal-decorators': 7.21.0_@babel+core@7.21.3 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-transform-runtime': 7.21.0_@babel+core@7.21.3 - '@babel/preset-env': 7.20.2_@babel+core@7.21.3 - '@babel/preset-react': 7.18.6_@babel+core@7.21.3 - '@babel/preset-typescript': 7.21.0_@babel+core@7.21.3 - '@babel/runtime': 7.21.0 - '@changesets/changelog-git': 0.1.14 - '@changesets/cli': 2.26.1 - '@changesets/config': 2.3.0 - '@starbeam-dev/build-support': link:workspace/build - '@starbeam/eslint-plugin': link:workspace/eslint - '@types/eslint': 8.21.3 - '@types/node': 18.15.5 - '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu - '@vitest/ui': 0.29.7 - eslint: 8.36.0 - eslint-config-airbnb: 19.0.4_guhfqc3yvckhutqwrddiy54d5i - eslint-config-prettier: 8.8.0_eslint@8.36.0 - eslint-import-resolver-typescript: 3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy - eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq - eslint-plugin-jsonc: 2.7.0_eslint@8.36.0 - eslint-plugin-prettier: 4.2.1_ose2zoovovx4ulolhifz3tfzx4 - eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0 - eslint-plugin-unused-imports: 2.0.0_pjgbsoxltfjhart6hcjsvw66hu - esno: 0.16.3 - fast-glob: 3.2.12 - happy-dom: 8.9.0 - jsdom: 21.1.1 - prettier: 2.8.6 - tslib: 2.5.0 - typescript: 5.0.2 - vite: 4.2.1_@types+node@18.15.5 - vitest: 0.29.7_bi73zdcwqjrbwiah6tn5sspwie + '@babel/eslint-parser': + specifier: ^7.21.3 + version: 7.21.3(@babel/core@7.21.3)(eslint@8.36.0) + '@babel/plugin-proposal-decorators': + specifier: ^7.21.0 + version: 7.21.0(@babel/core@7.21.3) + '@babel/plugin-syntax-dynamic-import': + specifier: ^7.8.3 + version: 7.8.3(@babel/core@7.21.3) + '@babel/plugin-transform-runtime': + specifier: ^7.21.0 + version: 7.21.0(@babel/core@7.21.3) + '@babel/preset-env': + specifier: ^7.20.2 + version: 7.20.2(@babel/core@7.21.3) + '@babel/preset-react': + specifier: ^7.18.6 + version: 7.18.6(@babel/core@7.21.3) + '@babel/preset-typescript': + specifier: ^7.21.0 + version: 7.21.0(@babel/core@7.21.3) + '@babel/runtime': + specifier: ^7.21.0 + version: 7.21.0 + '@changesets/changelog-git': + specifier: ^0.1.14 + version: 0.1.14 + '@changesets/cli': + specifier: ^2.26.1 + version: 2.26.1 + '@changesets/config': + specifier: ^2.3.0 + version: 2.3.0 + '@starbeam-dev/build-support': + specifier: workspace:1.0.0 + version: link:workspace/build + '@starbeam/eslint-plugin': + specifier: workspace:^1.0.0 + version: link:workspace/eslint + '@types/eslint': + specifier: ^8.21.3 + version: 8.21.3 + '@types/node': + specifier: 18.15.5 + version: 18.15.5 + '@typescript-eslint/eslint-plugin': + specifier: ^5.56.0 + version: 5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2) + '@typescript-eslint/parser': + specifier: ^5.56.0 + version: 5.56.0(eslint@8.36.0)(typescript@5.0.2) + '@vitest/ui': + specifier: ^0.29.8 + version: 0.29.8 + eslint: + specifier: ^8.36.0 + version: 8.36.0 + eslint-config-airbnb: + specifier: ^19.0.4 + version: 19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.36.0) + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.36.0) + eslint-import-resolver-typescript: + specifier: ^3.5.3 + version: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint-plugin-jsonc: + specifier: ^2.7.0 + version: 2.7.0(eslint@8.36.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.6) + eslint-plugin-simple-import-sort: + specifier: ^10.0.0 + version: 10.0.0(eslint@8.36.0) + eslint-plugin-unused-imports: + specifier: ^2.0.0 + version: 2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0) + esno: + specifier: ^0.16.3 + version: 0.16.3 + fast-glob: + specifier: ^3.2.12 + version: 3.2.12 + happy-dom: + specifier: ^8.9.0 + version: 8.9.0 + jsdom: + specifier: ^21.1.1 + version: 21.1.1 + prettier: + specifier: ^2.8.6 + version: 2.8.6 + tslib: + specifier: ^2.5.0 + version: 2.5.0 + typescript: + specifier: ^5.0.2 + version: 5.0.2 + vite: + specifier: 4.2.1 + version: 4.2.1(@types/node@18.15.5) + vitest: + specifier: 0.29.8 + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) '@types/@rollup/plugin-commonjs': - specifiers: - '@rollup/plugin-commonjs': ^24.0.0 dependencies: - '@rollup/plugin-commonjs': 24.0.0 + '@rollup/plugin-commonjs': + specifier: ^24.0.0 + version: 24.0.0 '@types/@rollup/plugin-node-resolve': - specifiers: - '@rollup/plugin-node-resolve': ^15.0.1 dependencies: - '@rollup/plugin-node-resolve': 15.0.1 + '@rollup/plugin-node-resolve': + specifier: ^15.0.1 + version: 15.0.1 '@types/ansicolor': - specifiers: - '@types/node': 18.15.5 devDependencies: - '@types/node': 18.15.5 + '@types/node': + specifier: 18.15.5 + version: 18.15.5 '@types/rollup-plugin-polyfill-node': - specifiers: - rollup: ^3.9.1 dependencies: - rollup: 3.9.1 + rollup: + specifier: ^3.9.1 + version: 3.9.1 '@types/shell-escape-tag': - specifiers: - '@types/node': 18.15.5 devDependencies: - '@types/node': 18.15.5 + '@types/node': + specifier: 18.15.5 + version: 18.15.5 '@types/shell-split': - specifiers: - '@types/node': 18.15.5 devDependencies: - '@types/node': 18.15.5 + '@types/node': + specifier: 18.15.5 + version: 18.15.5 demos/preact: - specifiers: - '@esbuild-plugins/node-globals-polyfill': ^0.1.1 - '@starbeam/js': workspace:^ - '@starbeam/preact': workspace:^ - '@starbeam/universal': workspace:^ - '@vitest/ui': '*' - preact: ^10.11.3 - purecss: ^3.0.0 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' dependencies: - '@starbeam/js': link:../../packages/universal/js - '@starbeam/preact': link:../../packages/preact/preact - '@starbeam/universal': link:../../packages/universal/universal - preact: 10.11.3 - purecss: 3.0.0 + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/preact': + specifier: workspace:^ + version: link:../../packages/preact/preact + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + preact: + specifier: ^10.11.3 + version: 10.11.3 + purecss: + specifier: ^3.0.0 + version: 3.0.0 devDependencies: - '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.17.12 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@esbuild-plugins/node-globals-polyfill': + specifier: ^0.1.1 + version: 0.1.1(esbuild@0.17.12) + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) demos/preact-hello-world: - specifiers: - '@esbuild-plugins/node-globals-polyfill': ^0.1.1 - '@starbeam/js': workspace:^ - '@starbeam/preact': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - '@vitest/ui': '*' - preact: ^10.11.3 - purecss: 3.0.0 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' dependencies: - '@starbeam/js': link:../../packages/universal/js - '@starbeam/preact': link:../../packages/preact/preact - '@starbeam/runtime': link:../../packages/universal/runtime - '@starbeam/universal': link:../../packages/universal/universal - preact: 10.11.3 - purecss: 3.0.0 + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/preact': + specifier: workspace:^ + version: link:../../packages/preact/preact + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../packages/universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + preact: + specifier: ^10.11.3 + version: 10.11.3 + purecss: + specifier: 3.0.0 + version: 3.0.0 devDependencies: - '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.17.12 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@esbuild-plugins/node-globals-polyfill': + specifier: ^0.1.1 + version: 0.1.1(esbuild@0.17.12) + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) demos/react: - specifiers: - '@starbeam/js': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/universal': workspace:^ - '@types/react': ^18.0.26 - '@types/react-dom': ^18.0.10 - '@vitest/ui': '*' - purecss: 3.0.0 - react: ^18.1.0 - react-dom: ^18.1.0 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' dependencies: - '@starbeam/js': link:../../packages/universal/js - '@starbeam/react': link:../../packages/react/react - '@starbeam/universal': link:../../packages/universal/universal - purecss: 3.0.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/react': + specifier: workspace:^ + version: link:../../packages/react/react + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + purecss: + specifier: 3.0.0 + version: 3.0.0 + react: + specifier: ^18.1.0 + version: 18.2.0 + react-dom: + specifier: ^18.1.0 + version: 18.2.0(react@18.2.0) devDependencies: - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + '@types/react-dom': + specifier: ^18.0.10 + version: 18.0.10 + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) demos/react-jsnation: - specifiers: - '@starbeam/debug': workspace:^ - '@starbeam/js': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/universal': workspace:^ - '@types/react': ^18.0.26 - '@types/react-dom': ^18.0.10 - '@vitest/ui': '*' - purecss: 3.0.0 - react: ^18.1.0 - react-dom: ^18.1.0 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 dependencies: - '@starbeam/debug': link:../../packages/universal/debug - '@starbeam/js': link:../../packages/universal/js - '@starbeam/react': link:../../packages/react/react - '@starbeam/universal': link:../../packages/universal/universal - purecss: 3.0.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + '@starbeam/debug': + specifier: workspace:^ + version: link:../../packages/universal/debug + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/react': + specifier: workspace:^ + version: link:../../packages/react/react + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + purecss: + specifier: 3.0.0 + version: 3.0.0 + react: + specifier: ^18.1.0 + version: 18.2.0 + react-dom: + specifier: ^18.1.0 + version: 18.2.0(react@18.2.0) devDependencies: - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + '@types/react-dom': + specifier: ^18.0.10 + version: 18.0.10 + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) demos/react-jsnation/tests: - specifiers: - '@starbeam-demos/react-jsnation': workspace:^ - '@starbeam-workspace/react-test-utils': workspace:^ - '@starbeam-workspace/test-utils': workspace:^ - '@testing-library/react': ^13.4.0 - '@types/react': ^18.0.26 - react: '*' - react-dom: '*' - react-error-boundary: ^3.1.4 dependencies: - '@starbeam-demos/react-jsnation': link:.. - '@starbeam-workspace/react-test-utils': link:../../../packages/react/test-utils - '@starbeam-workspace/test-utils': link:../../../packages/universal/test-utils - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - react-error-boundary: 3.1.4_react@18.2.0 + '@starbeam-demos/react-jsnation': + specifier: workspace:^ + version: link:.. + '@starbeam-workspace/react-test-utils': + specifier: workspace:^ + version: link:../../../packages/react/test-utils + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../packages/universal/test-utils + react: + specifier: '*' + version: 18.2.0 + react-dom: + specifier: '*' + version: 18.2.0(react@18.2.0) + react-error-boundary: + specifier: ^3.1.4 + version: 3.1.4(react@18.2.0) devDependencies: - '@testing-library/react': 13.4.0_biqbaboplfbrettd7655fr4n2y - '@types/react': 18.0.26 + '@testing-library/react': + specifier: ^13.4.0 + version: 13.4.0(react-dom@18.2.0)(react@18.2.0) + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 demos/react-lite-query: - specifiers: - '@starbeam/debug': workspace:^ - '@starbeam/js': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeam/verify': workspace:^ - '@starbeamx/devtool': workspace:^ - '@types/react': ^18.0.26 - '@types/react-dom': ^18.0.10 - '@vitest/ui': '*' - axios: ^1.2.2 - react: ^18.1.0 - react-dom: ^18.1.0 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' - dependencies: - '@starbeam/debug': link:../../packages/universal/debug - '@starbeam/js': link:../../packages/universal/js - '@starbeam/react': link:../../packages/react/react - '@starbeam/universal': link:../../packages/universal/universal - '@starbeam/verify': link:../../packages/universal/verify - '@starbeamx/devtool': link:../../packages/x/devtool - axios: 1.2.2 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../../packages/universal/debug + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/react': + specifier: workspace:^ + version: link:../../packages/react/react + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../../packages/universal/verify + '@starbeamx/devtool': + specifier: workspace:^ + version: link:../../packages/x/devtool + axios: + specifier: ^1.2.2 + version: 1.2.2 + react: + specifier: ^18.1.0 + version: 18.2.0 + react-dom: + specifier: ^18.1.0 + version: 18.2.0(react@18.2.0) devDependencies: - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + '@types/react-dom': + specifier: ^18.0.10 + version: 18.0.10 + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) demos/react-query: - specifiers: - '@shopify/polaris': ^10.16.1 - '@starbeam/js': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeamx/devtool': workspace:^ - '@types/react': ^18.0.26 - '@types/react-dom': ^18.0.10 - '@types/styled-components': ^5.1.25 - '@vitest/ui': '*' - axios: ^1.2.2 - purecss: 3.0.0 - react: ^18 - react-dom: ^18 - styled-components: ^5.3.5 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' - dependencies: - '@starbeam/js': link:../../packages/universal/js - '@starbeam/react': link:../../packages/react/react - '@starbeam/universal': link:../../packages/universal/universal - '@starbeamx/devtool': link:../../packages/x/devtool - purecss: 3.0.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + dependencies: + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/react': + specifier: workspace:^ + version: link:../../packages/react/react + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + '@starbeamx/devtool': + specifier: workspace:^ + version: link:../../packages/x/devtool + purecss: + specifier: 3.0.0 + version: 3.0.0 + react: + specifier: ^18 + version: 18.2.0 + react-dom: + specifier: ^18 + version: 18.2.0(react@18.2.0) devDependencies: - '@shopify/polaris': 10.16.1_biqbaboplfbrettd7655fr4n2y - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 - '@types/styled-components': 5.1.26 - '@vitest/ui': 0.29.7 - axios: 1.2.2 - styled-components: 5.3.6_pumtretovylab5lwhztzjp2kuy - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@shopify/polaris': + specifier: ^10.16.1 + version: 10.16.1(react-dom@18.2.0)(react@18.2.0) + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + '@types/react-dom': + specifier: ^18.0.10 + version: 18.0.10 + '@types/styled-components': + specifier: ^5.1.25 + version: 5.1.26 + '@vitest/ui': + specifier: '*' + version: 0.29.7 + axios: + specifier: ^1.2.2 + version: 1.2.2 + styled-components: + specifier: ^5.3.5 + version: 5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) demos/react-stock-ticker: - specifiers: - '@starbeam/js': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeamx/devtool': workspace:* - '@types/react': ^18.0.26 - '@types/react-dom': ^18.0.10 - '@types/react-portal': ^4.0.4 - '@vitest/ui': '*' - react: ^18.1.0 - react-dom: ^18.1.0 - react-portal: ^4.2.2 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' dependencies: - '@starbeam/js': link:../../packages/universal/js - '@starbeam/react': link:../../packages/react/react - '@starbeam/universal': link:../../packages/universal/universal - '@starbeamx/devtool': link:../../packages/x/devtool - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - react-portal: 4.2.2_biqbaboplfbrettd7655fr4n2y + '@starbeam/js': + specifier: workspace:^ + version: link:../../packages/universal/js + '@starbeam/react': + specifier: workspace:^ + version: link:../../packages/react/react + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + '@starbeamx/devtool': + specifier: workspace:* + version: link:../../packages/x/devtool + react: + specifier: ^18.1.0 + version: 18.2.0 + react-dom: + specifier: ^18.1.0 + version: 18.2.0(react@18.2.0) + react-portal: + specifier: ^4.2.2 + version: 4.2.2(react-dom@18.2.0)(react@18.2.0) devDependencies: - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 - '@types/react-portal': 4.0.4 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + '@types/react-dom': + specifier: ^18.0.10 + version: 18.0.10 + '@types/react-portal': + specifier: ^4.0.4 + version: 4.0.4 + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) demos/react-store: - specifiers: - '@starbeam/debug': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeamx/devtool': workspace:^ - '@starbeamx/store': workspace:^ - '@types/react': ^18.0.26 - '@types/react-dom': ^18.0.10 - '@vitest/ui': '*' - purecss: 3.0.0 - react: ^18.1.0 - react-dom: ^18.1.0 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - vitest: '*' - dependencies: - '@starbeam/debug': link:../../packages/universal/debug - '@starbeam/react': link:../../packages/react/react - '@starbeam/universal': link:../../packages/universal/universal - '@starbeamx/devtool': link:../../packages/x/devtool - '@starbeamx/store': link:../../packages/x/store - purecss: 3.0.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../../packages/universal/debug + '@starbeam/react': + specifier: workspace:^ + version: link:../../packages/react/react + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + '@starbeamx/devtool': + specifier: workspace:^ + version: link:../../packages/x/devtool + '@starbeamx/store': + specifier: workspace:^ + version: link:../../packages/x/store + purecss: + specifier: 3.0.0 + version: 3.0.0 + react: + specifier: ^18.1.0 + version: 18.2.0 + react-dom: + specifier: ^18.1.0 + version: 18.2.0(react@18.2.0) devDependencies: - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 - '@vitest/ui': 0.29.7 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0_vite@4.2.1 - vitest: 0.29.7_@vitest+ui@0.29.7 + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + '@types/react-dom': + specifier: ^18.0.10 + version: 18.0.10 + '@vitest/ui': + specifier: '*' + version: 0.29.7 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) + vitest: + specifier: '*' + version: 0.29.7(@vitest/ui@0.29.7) packages/preact/preact: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/preact-utils': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeam/verify': workspace:^ - chalk: ^5.2.0 - preact: ^10.11.3 - preact-render-to-string: ^5.2.5 - dependencies: - '@starbeam/core-utils': link:../../universal/core-utils - '@starbeam/debug': link:../../universal/debug - '@starbeam/interfaces': link:../../universal/interfaces - '@starbeam/preact-utils': link:../preact-utils - '@starbeam/reactive': link:../../universal/reactive - '@starbeam/runtime': link:../../universal/runtime - '@starbeam/tags': link:../../universal/tags - '@starbeam/universal': link:../../universal/universal - '@starbeam/verify': link:../../universal/verify - preact: 10.11.3 + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../../universal/core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../universal/debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../universal/interfaces + '@starbeam/preact-utils': + specifier: workspace:^ + version: link:../preact-utils + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../universal/reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../universal/runtime + '@starbeam/tags': + specifier: workspace:^ + version: link:../../universal/tags + '@starbeam/universal': + specifier: workspace:^ + version: link:../../universal/universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../../universal/verify + preact: + specifier: ^10.11.3 + version: 10.11.3 devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build - chalk: 5.2.0 - preact-render-to-string: 5.2.6_preact@10.11.3 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + chalk: + specifier: ^5.2.0 + version: 5.2.0 + preact-render-to-string: + specifier: ^5.2.5 + version: 5.2.6(preact@10.11.3) packages/preact/preact-testing-utils: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/verify': workspace:^ - '@testing-library/dom': ^8.19.1 - '@testing-library/preact': ^3.2.2 - htm: ^3.1.1 - preact: '*' - preact-render-to-string: ^5.2.6 - dependencies: - '@starbeam/verify': link:../../universal/verify - '@testing-library/dom': 8.19.1 - '@testing-library/preact': 3.2.2_preact@10.11.3 - htm: 3.1.1 - preact: 10.11.3 + dependencies: + '@starbeam/verify': + specifier: workspace:^ + version: link:../../universal/verify + '@testing-library/dom': + specifier: ^8.19.1 + version: 8.19.1 + '@testing-library/preact': + specifier: ^3.2.2 + version: 3.2.2(preact@10.11.3) + htm: + specifier: ^3.1.1 + version: 3.1.1 + preact: + specifier: '*' + version: 10.11.3 devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build - preact-render-to-string: 5.2.6_preact@10.11.3 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + preact-render-to-string: + specifier: ^5.2.6 + version: 5.2.6(preact@10.11.3) packages/preact/preact-testing-utils/tests: - specifiers: - '@starbeam-workspace/preact-testing-utils': workspace:^ - '@starbeam-workspace/test-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/preact': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - '@testing-library/dom': ^8.19.1 - '@testing-library/preact': ^3.2.2 - htm: ^3.1.1 - jsdom: ^20.0.3 - preact: ^10.11.3 - preact-render-to-string: ^5.2.5 - dependencies: - '@starbeam-workspace/preact-testing-utils': link:.. - '@starbeam-workspace/test-utils': link:../../../universal/test-utils - '@starbeam/debug': link:../../../universal/debug - '@starbeam/preact': link:../../preact - '@starbeam/runtime': link:../../../universal/runtime - '@starbeam/universal': link:../../../universal/universal - '@testing-library/dom': 8.19.1 - '@testing-library/preact': 3.2.2_preact@10.11.3 - htm: 3.1.1 - jsdom: 20.0.3 - preact: 10.11.3 + dependencies: + '@starbeam-workspace/preact-testing-utils': + specifier: workspace:^ + version: link:.. + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../universal/test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../../universal/debug + '@starbeam/preact': + specifier: workspace:^ + version: link:../../preact + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../../universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../../universal/universal + '@testing-library/dom': + specifier: ^8.19.1 + version: 8.19.1 + '@testing-library/preact': + specifier: ^3.2.2 + version: 3.2.2(preact@10.11.3) + htm: + specifier: ^3.1.1 + version: 3.1.1 + jsdom: + specifier: ^20.0.3 + version: 20.0.3 + preact: + specifier: ^10.11.3 + version: 10.11.3 devDependencies: - preact-render-to-string: 5.2.6_preact@10.11.3 + preact-render-to-string: + specifier: ^5.2.5 + version: 5.2.6(preact@10.11.3) packages/preact/preact-utils: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:* - preact: '>=10' dependencies: - '@starbeam/core-utils': link:../../universal/core-utils - preact: 10.11.3 + '@starbeam/core-utils': + specifier: workspace:* + version: link:../../universal/core-utils + preact: + specifier: '>=10' + version: 10.11.3 devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/preact/preact-utils/tests: - specifiers: - '@starbeam-workspace/test-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/preact': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - '@testing-library/dom': ^8.19.1 - '@testing-library/preact': ^3.2.2 - htm: ^3.1.1 - jsdom: ^20.0.3 - preact: ^10.11.3 - preact-render-to-string: ^5.2.5 - dependencies: - '@starbeam-workspace/test-utils': link:../../../universal/test-utils - '@starbeam/debug': link:../../../universal/debug - '@starbeam/preact': link:../../preact - '@starbeam/runtime': link:../../../universal/runtime - '@starbeam/universal': link:../../../universal/universal - '@testing-library/dom': 8.19.1 - '@testing-library/preact': 3.2.2_preact@10.11.3 - htm: 3.1.1 - jsdom: 20.0.3 - preact: 10.11.3 + dependencies: + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../universal/test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../../universal/debug + '@starbeam/preact': + specifier: workspace:^ + version: link:../../preact + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../../universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../../universal/universal + '@testing-library/dom': + specifier: ^8.19.1 + version: 8.19.1 + '@testing-library/preact': + specifier: ^3.2.2 + version: 3.2.2(preact@10.11.3) + htm: + specifier: ^3.1.1 + version: 3.1.1 + jsdom: + specifier: ^20.0.3 + version: 20.0.3 + preact: + specifier: ^10.11.3 + version: 10.11.3 devDependencies: - preact-render-to-string: 5.2.6_preact@10.11.3 + preact-render-to-string: + specifier: ^5.2.5 + version: 5.2.6(preact@10.11.3) packages/preact/preact/tests: - specifiers: - '@starbeam-workspace/preact-testing-utils': workspace:^ - '@starbeam-workspace/test-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/preact': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - '@testing-library/dom': ^8.19.1 - '@testing-library/preact': ^3.2.2 - jsdom: ^20.0.3 - preact: ^10.11.3 - preact-render-to-string: ^5.2.5 - dependencies: - '@starbeam-workspace/preact-testing-utils': link:../../preact-testing-utils - '@starbeam-workspace/test-utils': link:../../../universal/test-utils - '@starbeam/debug': link:../../../universal/debug - '@starbeam/preact': link:.. - '@starbeam/runtime': link:../../../universal/runtime - '@starbeam/universal': link:../../../universal/universal - '@testing-library/dom': 8.19.1 - '@testing-library/preact': 3.2.2_preact@10.11.3 - jsdom: 20.0.3 - preact: 10.11.3 + dependencies: + '@starbeam-workspace/preact-testing-utils': + specifier: workspace:^ + version: link:../../preact-testing-utils + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../universal/test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../../universal/debug + '@starbeam/preact': + specifier: workspace:^ + version: link:.. + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../../universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../../universal/universal + '@testing-library/dom': + specifier: ^8.19.1 + version: 8.19.1 + '@testing-library/preact': + specifier: ^3.2.2 + version: 3.2.2(preact@10.11.3) + jsdom: + specifier: ^20.0.3 + version: 20.0.3 + preact: + specifier: ^10.11.3 + version: 10.11.3 devDependencies: - preact-render-to-string: 5.2.6_preact@10.11.3 + preact-render-to-string: + specifier: ^5.2.5 + version: 5.2.6(preact@10.11.3) packages/react/react: - specifiers: - '@domtree/flavors': workspace:^ - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/js': workspace:^ - '@starbeam/modifier': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeam/use-strict-lifecycle': workspace:^ - '@starbeam/verify': workspace:^ - '@types/node': 18.15.5 - '@types/react': ^18.0.28 - react: '*' - react-dom: '*' dependencies: - '@starbeam/core-utils': link:../../universal/core-utils - '@starbeam/debug': link:../../universal/debug - '@starbeam/interfaces': link:../../universal/interfaces - '@starbeam/js': link:../../universal/js - '@starbeam/modifier': link:../../universal/modifier - '@starbeam/reactive': link:../../universal/reactive - '@starbeam/runtime': link:../../universal/runtime - '@starbeam/shared': link:../../universal/shared - '@starbeam/universal': link:../../universal/universal - '@starbeam/use-strict-lifecycle': link:../use-strict-lifecycle - '@starbeam/verify': link:../../universal/verify - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../../universal/core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../universal/debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../universal/interfaces + '@starbeam/js': + specifier: workspace:^ + version: link:../../universal/js + '@starbeam/modifier': + specifier: workspace:^ + version: link:../../universal/modifier + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../universal/reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../universal/runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../../universal/shared + '@starbeam/universal': + specifier: workspace:^ + version: link:../../universal/universal + '@starbeam/use-strict-lifecycle': + specifier: workspace:^ + version: link:../use-strict-lifecycle + '@starbeam/verify': + specifier: workspace:^ + version: link:../../universal/verify + react: + specifier: '*' + version: 18.2.0 + react-dom: + specifier: '*' + version: 18.2.0(react@18.2.0) devDependencies: - '@domtree/flavors': link:../../../workspace/@domtree/flavors - '@starbeam-dev/build-support': link:../../../workspace/build - '@types/node': 18.15.5 - '@types/react': 18.0.28 + '@domtree/flavors': + specifier: workspace:^ + version: link:../../../workspace/@domtree/flavors + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + '@types/node': + specifier: 18.15.5 + version: 18.15.5 + '@types/react': + specifier: ^18.0.28 + version: 18.0.28 packages/react/react/tests: - specifiers: - '@starbeam-workspace/react-test-utils': workspace:^ - '@starbeam-workspace/test-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/react': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - jsdom: ^21.1.1 - react: ^18.2.0 - vitest: '*' - dependencies: - '@starbeam-workspace/react-test-utils': link:../../test-utils - '@starbeam-workspace/test-utils': link:../../../universal/test-utils - '@starbeam/debug': link:../../../universal/debug - '@starbeam/react': link:.. - '@starbeam/reactive': link:../../../universal/reactive - '@starbeam/runtime': link:../../../universal/runtime - '@starbeam/universal': link:../../../universal/universal - jsdom: 21.1.1 - react: 18.2.0 - vitest: 0.29.7_jsdom@21.1.1 + dependencies: + '@starbeam-workspace/react-test-utils': + specifier: workspace:^ + version: link:../../test-utils + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../universal/test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../../universal/debug + '@starbeam/react': + specifier: workspace:^ + version: link:.. + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../../universal/reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../../universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../../universal/universal + jsdom: + specifier: ^21.1.1 + version: 21.1.1 + react: + specifier: ^18.2.0 + version: 18.2.0 + vitest: + specifier: '*' + version: 0.29.7(jsdom@21.1.1) packages/react/test-utils: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/test-utils': workspace:^ - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/verify': workspace:^ - '@testing-library/react': ^14.0.0 - '@types/react': ^18.0.26 - react: '*' - react-dom: '*' dependencies: - '@starbeam-workspace/test-utils': link:../../universal/test-utils - '@starbeam/core-utils': link:../../universal/core-utils - '@starbeam/debug': link:../../universal/debug - '@starbeam/shared': link:../../universal/shared - '@starbeam/verify': link:../../universal/verify - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../universal/test-utils + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../../universal/core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../universal/debug + '@starbeam/shared': + specifier: workspace:^ + version: link:../../universal/shared + '@starbeam/verify': + specifier: workspace:^ + version: link:../../universal/verify + react: + specifier: '*' + version: 18.2.0 + react-dom: + specifier: '*' + version: 18.2.0(react@18.2.0) devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build - '@testing-library/react': 14.0.0_biqbaboplfbrettd7655fr4n2y - '@types/react': 18.0.26 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + '@testing-library/react': + specifier: ^14.0.0 + version: 14.0.0(react-dom@18.2.0)(react@18.2.0) + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 packages/react/use-strict-lifecycle: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@types/react': ^18.0.26 - react: '*' - react-dom: '*' dependencies: - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react: + specifier: '*' + version: 18.2.0 + react-dom: + specifier: '*' + version: 18.2.0(react@18.2.0) devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build - '@types/react': 18.0.26 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 packages/react/use-strict-lifecycle/tests: - specifiers: - '@starbeam-workspace/react-test-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/use-strict-lifecycle': workspace:^ - '@types/react': ^18.0.26 - jsdom: ^20.0.3 - react: 18.2.0 dependencies: - '@starbeam-workspace/react-test-utils': link:../../test-utils - '@starbeam/debug': link:../../../universal/debug - '@starbeam/use-strict-lifecycle': link:.. - react: 18.2.0 + '@starbeam-workspace/react-test-utils': + specifier: workspace:^ + version: link:../../test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../../universal/debug + '@starbeam/use-strict-lifecycle': + specifier: workspace:^ + version: link:.. + react: + specifier: 18.2.0 + version: 18.2.0 devDependencies: - '@types/react': 18.0.26 - jsdom: 20.0.3 + '@types/react': + specifier: ^18.0.26 + version: 18.0.26 + jsdom: + specifier: ^20.0.3 + version: 20.0.3 packages/universal/core: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/universal': workspace:^ dependencies: - '@starbeam/universal': link:../universal + '@starbeam/universal': + specifier: workspace:^ + version: link:../universal devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/core-utils: - specifiers: - '@starbeam-dev/build-support': workspace:* devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/core-utils/tests: - specifiers: - '@starbeam/core-utils': workspace:^ dependencies: - '@starbeam/core-utils': link:.. + '@starbeam/core-utils': + specifier: workspace:^ + version: link:.. packages/universal/debug: - specifiers: - '@domtree/flavors': workspace:^ - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/verify': workspace:^ - '@types/ansicolor': workspace:^ - '@types/node': 18.15.5 - ansicolor: ^1.1.100 - buffer: ^6.0.3 - stacktracey: ^2.1.8 - dependencies: - '@domtree/flavors': link:../../../workspace/@domtree/flavors - '@starbeam/core-utils': link:../core-utils - '@starbeam/interfaces': link:../interfaces - '@starbeam/shared': link:../shared - '@starbeam/verify': link:../verify - ansicolor: 1.1.100 - buffer: 6.0.3 - stacktracey: 2.1.8 + dependencies: + '@domtree/flavors': + specifier: workspace:^ + version: link:../../../workspace/@domtree/flavors + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify + ansicolor: + specifier: ^1.1.100 + version: 1.1.100 + buffer: + specifier: ^6.0.3 + version: 6.0.3 + stacktracey: + specifier: ^2.1.8 + version: 2.1.8 devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build - '@types/ansicolor': link:../../../@types/ansicolor - '@types/node': 18.15.5 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + '@types/ansicolor': + specifier: workspace:^ + version: link:../../../@types/ansicolor + '@types/node': + specifier: 18.15.5 + version: 18.15.5 packages/universal/debug/tests: - specifiers: - '@starbeam/debug': workspace:^ dependencies: - '@starbeam/debug': link:.. + '@starbeam/debug': + specifier: workspace:^ + version: link:.. packages/universal/interfaces: - specifiers: - '@domtree/any': workspace:^ - '@starbeam/shared': workspace:^ dependencies: - '@domtree/any': link:../../../workspace/@domtree/any - '@starbeam/shared': link:../shared + '@domtree/any': + specifier: workspace:^ + version: link:../../../workspace/@domtree/any + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared packages/universal/js: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeam/verify': workspace:^ - dependencies: - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/reactive': link:../reactive - '@starbeam/runtime': link:../runtime - '@starbeam/shared': link:../shared - '@starbeam/tags': link:../tags - '@starbeam/universal': link:../universal - '@starbeam/verify': link:../verify + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags + '@starbeam/universal': + specifier: workspace:^ + version: link:../universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/js/tests: - specifiers: - '@starbeam/js': workspace:^ - '@starbeam/universal': workspace:^ dependencies: - '@starbeam/js': link:.. - '@starbeam/universal': link:../../universal + '@starbeam/js': + specifier: workspace:^ + version: link:.. + '@starbeam/universal': + specifier: workspace:^ + version: link:../../universal packages/universal/modifier: - specifiers: - '@domtree/flavors': workspace:^ - '@starbeam-dev/build-support': workspace:* - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeam/verify': workspace:^ - dependencies: - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/shared': link:../shared - '@starbeam/tags': link:../tags - '@starbeam/universal': link:../universal - '@starbeam/verify': link:../verify + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags + '@starbeam/universal': + specifier: workspace:^ + version: link:../universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify devDependencies: - '@domtree/flavors': link:../../../workspace/@domtree/flavors - '@starbeam-dev/build-support': link:../../../workspace/build + '@domtree/flavors': + specifier: workspace:^ + version: link:../../../workspace/@domtree/flavors + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/reactive: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/tags': workspace:^ - dependencies: - '@starbeam/core-utils': link:../core-utils - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/shared': link:../shared - '@starbeam/tags': link:../tags + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/reactive/tests: - specifiers: - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/shared': workspace:^ - dependencies: - '@starbeam/debug': link:../../debug - '@starbeam/interfaces': link:../../interfaces - '@starbeam/reactive': link:.. - '@starbeam/runtime': link:../../runtime - '@starbeam/shared': link:../../shared + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:.. + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../../shared + + packages/universal/resource: + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + devDependencies: + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + + packages/universal/resource/tests: + dependencies: + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../interfaces + '@starbeam/js': + specifier: workspace:^ + version: link:../../js + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:.. + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../../shared packages/universal/runtime: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/verify': workspace:^ - dependencies: - '@starbeam/core-utils': link:../core-utils - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/reactive': link:../reactive - '@starbeam/shared': link:../shared - '@starbeam/tags': link:../tags - '@starbeam/verify': link:../verify + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/runtime/tests: - specifiers: - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/shared': workspace:^ - dependencies: - '@starbeam/debug': link:../../debug - '@starbeam/interfaces': link:../../interfaces - '@starbeam/reactive': link:../../reactive - '@starbeam/runtime': link:.. - '@starbeam/shared': link:../../shared + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:.. + '@starbeam/shared': + specifier: workspace:^ + version: link:../../shared packages/universal/shared: - specifiers: - '@starbeam-dev/build-support': workspace:* devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/shared/tests: - specifiers: - '@starbeam/shared': workspace:^ dependencies: - '@starbeam/shared': link:.. + '@starbeam/shared': + specifier: workspace:^ + version: link:.. packages/universal/tags: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/shared': workspace:^ - dependencies: - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/shared': link:../shared + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/test-utils: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - '@starbeam/verify': workspace:^ - dependencies: - '@starbeam/runtime': link:../runtime - '@starbeam/universal': link:../universal - '@starbeam/verify': link:../verify + dependencies: + '@starbeam/runtime': + specifier: workspace:^ + version: link:../runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/universal: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/reactive': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/shared': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/verify': workspace:^ - dependencies: - '@starbeam/core-utils': link:../core-utils - '@starbeam/debug': link:../debug - '@starbeam/interfaces': link:../interfaces - '@starbeam/reactive': link:../reactive - '@starbeam/runtime': link:../runtime - '@starbeam/shared': link:../shared - '@starbeam/tags': link:../tags - '@starbeam/verify': link:../verify + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../resource + '@starbeam/runtime': + specifier: workspace:^ + version: link:../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags + '@starbeam/universal': + specifier: workspace:^ + version: 'link:' + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/universal/tests: - specifiers: - '@starbeam-workspace/test-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/js': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - dependencies: - '@starbeam/debug': link:../../debug - '@starbeam/js': link:../../js - '@starbeam/runtime': link:../../runtime - '@starbeam/universal': link:.. + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../../debug + '@starbeam/js': + specifier: workspace:^ + version: link:../../js + '@starbeam/resource': + specifier: workspace:^ + version: link:../../resource + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:.. devDependencies: - '@starbeam-workspace/test-utils': link:../../test-utils + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../test-utils packages/universal/verify: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ dependencies: - '@starbeam/core-utils': link:../core-utils + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/universal/verify/tests: - specifiers: - '@starbeam/verify': workspace:^ dependencies: - '@starbeam/verify': link:.. + '@starbeam/verify': + specifier: workspace:^ + version: link:.. packages/x/devtool: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/core-utils': workspace:^ - '@starbeam/debug': workspace:^ - '@starbeam/interfaces': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/tags': workspace:^ - '@starbeam/verify': workspace:^ - preact: ^10.11.3 - dependencies: - '@starbeam/core-utils': link:../../universal/core-utils - '@starbeam/debug': link:../../universal/debug - '@starbeam/interfaces': link:../../universal/interfaces - '@starbeam/runtime': link:../../universal/runtime - '@starbeam/tags': link:../../universal/tags - '@starbeam/verify': link:../../universal/verify - preact: 10.11.3 + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../../universal/core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../universal/debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../universal/interfaces + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../universal/runtime + '@starbeam/tags': + specifier: workspace:^ + version: link:../../universal/tags + '@starbeam/verify': + specifier: workspace:^ + version: link:../../universal/verify + preact: + specifier: ^10.11.3 + version: 10.11.3 devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/x/devtools-extension: - specifiers: - '@crxjs/vite-plugin': beta - chrome-types: ^0.1.159 - dirfilename: ^1.0.4 - preact: ^10.11.3 - vite: 4.2.1 - vite-plugin-mpa: ^1.1.3 devDependencies: - '@crxjs/vite-plugin': 2.0.0-beta.15 - chrome-types: 0.1.159 - dirfilename: 1.1.1 - preact: 10.11.3 - vite: 4.2.1 - vite-plugin-mpa: 1.1.4 + '@crxjs/vite-plugin': + specifier: beta + version: 2.0.0-beta.15 + chrome-types: + specifier: ^0.1.159 + version: 0.1.159 + dirfilename: + specifier: ^1.0.4 + version: 1.1.1 + preact: + specifier: ^10.11.3 + version: 10.11.3 + vite: + specifier: 4.2.1 + version: 4.2.1 + vite-plugin-mpa: + specifier: ^1.1.3 + version: 1.1.4 packages/x/store: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/debug': workspace:^ - '@starbeam/js': workspace:^ dependencies: - '@starbeam/debug': link:../../universal/debug - '@starbeam/js': link:../../universal/js + '@starbeam/debug': + specifier: workspace:^ + version: link:../../universal/debug + '@starbeam/js': + specifier: workspace:^ + version: link:../../universal/js devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/x/store/tests: - specifiers: - '@faker-js/faker': ^7.5.0 - '@starbeam/universal': workspace:^ - '@starbeam/verify': workspace:^ - '@starbeamx/store': workspace:^ dependencies: - '@faker-js/faker': 7.6.0 - '@starbeam/universal': link:../../../universal/universal - '@starbeam/verify': link:../../../universal/verify - '@starbeamx/store': link:.. + '@faker-js/faker': + specifier: ^7.5.0 + version: 7.6.0 + '@starbeam/universal': + specifier: workspace:^ + version: link:../../../universal/universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../../../universal/verify + '@starbeamx/store': + specifier: workspace:^ + version: link:.. packages/x/vanilla: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam/debug': workspace:^ - '@starbeam/runtime': workspace:^ - '@starbeam/universal': workspace:^ - dependencies: - '@starbeam/debug': link:../../universal/debug - '@starbeam/runtime': link:../../universal/runtime - '@starbeam/universal': link:../../universal/universal + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../../universal/debug + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../universal/universal devDependencies: - '@starbeam-dev/build-support': link:../../../workspace/build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build packages/x/vanilla/tests: - specifiers: - '@starbeam/universal': workspace:^ - '@starbeamx/vanilla': workspace:^ dependencies: - '@starbeam/universal': link:../../../universal/universal - '@starbeamx/vanilla': link:.. + '@starbeam/universal': + specifier: workspace:^ + version: link:../../../universal/universal + '@starbeamx/vanilla': + specifier: workspace:^ + version: link:.. workspace/@domtree/any: - specifiers: - '@domtree/browser': workspace:^ - '@domtree/interface': workspace:^ - '@domtree/minimal': workspace:^ - '@starbeam-dev/build-support': workspace:* - dependencies: - '@domtree/browser': link:../browser - '@domtree/interface': link:../interface - '@domtree/minimal': link:../minimal + dependencies: + '@domtree/browser': + specifier: workspace:^ + version: link:../browser + '@domtree/interface': + specifier: workspace:^ + version: link:../interface + '@domtree/minimal': + specifier: workspace:^ + version: link:../minimal devDependencies: - '@starbeam-dev/build-support': link:../../build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../build workspace/@domtree/browser: - specifiers: - '@domtree/interface': workspace:^ - '@starbeam-dev/build-support': workspace:* dependencies: - '@domtree/interface': link:../interface + '@domtree/interface': + specifier: workspace:^ + version: link:../interface devDependencies: - '@starbeam-dev/build-support': link:../../build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../build workspace/@domtree/flavors: - specifiers: - '@domtree/any': workspace:^ - '@domtree/browser': workspace:^ - '@domtree/minimal': workspace:^ - '@starbeam-dev/build-support': workspace:* - dependencies: - '@domtree/any': link:../any - '@domtree/browser': link:../browser - '@domtree/minimal': link:../minimal + dependencies: + '@domtree/any': + specifier: workspace:^ + version: link:../any + '@domtree/browser': + specifier: workspace:^ + version: link:../browser + '@domtree/minimal': + specifier: workspace:^ + version: link:../minimal devDependencies: - '@starbeam-dev/build-support': link:../../build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../build workspace/@domtree/interface: - specifiers: - '@starbeam-dev/build-support': workspace:* devDependencies: - '@starbeam-dev/build-support': link:../../build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../build workspace/@domtree/minimal: - specifiers: - '@domtree/interface': workspace:^ - '@starbeam-dev/build-support': workspace:* dependencies: - '@domtree/interface': link:../interface + '@domtree/interface': + specifier: workspace:^ + version: link:../interface devDependencies: - '@starbeam-dev/build-support': link:../../build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../build workspace/build: - specifiers: - '@esbuild-plugins/node-globals-polyfill': ^0.1.1 - '@eslint/eslintrc': ^1.4.1 - '@rollup/plugin-commonjs': ^24.0.0 - '@rollup/plugin-node-resolve': ^15.0.1 - '@types/node': 18.15.5 - '@types/rollup-plugin-polyfill-node': workspace:* - '@types/rollup__plugin-commonjs': workspace:^ - '@types/rollup__plugin-node-resolve': workspace:^ - '@typescript-eslint/parser': ^5.56.0 - eslint: ^8.36.0 - eslint-config-prettier: ^8.8.0 - eslint-plugin-import: ^2.27.5 - eslint-plugin-json: ^3.1.0 - eslint-plugin-prettier: ^4.2.1 - eslint-plugin-simple-import-sort: ^10.0.0 - eslint-plugin-unused-imports: ^2.0.0 - magic-string: ^0.27.0 - postcss: ^8.4.20 - rollup: ^3.9.1 - rollup-plugin-polyfill-node: ^0.11.0 - rollup-plugin-postcss: ^4.0.2 - rollup-plugin-ts: '*' - typescript: ^5.0.2 - vite: 4.2.1 - vite-plugin-fonts: 0.7.0 - dependencies: - '@esbuild-plugins/node-globals-polyfill': 0.1.1_esbuild@0.17.12 - '@eslint/eslintrc': 1.4.1 - '@rollup/plugin-commonjs': 24.0.0_rollup@3.9.1 - '@rollup/plugin-node-resolve': 15.0.1_rollup@3.9.1 - '@types/rollup-plugin-polyfill-node': link:../../@types/rollup-plugin-polyfill-node - '@types/rollup__plugin-commonjs': link:../../@types/@rollup/plugin-commonjs - '@types/rollup__plugin-node-resolve': link:../../@types/@rollup/plugin-node-resolve - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu - eslint: 8.36.0 - eslint-config-prettier: 8.8.0_eslint@8.36.0 - eslint-plugin-import: 2.27.5_cnkxirszkzb4o6ts7gbclno24e - eslint-plugin-json: 3.1.0 - eslint-plugin-prettier: 4.2.1_ose2zoovovx4ulolhifz3tfzx4 - eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0 - eslint-plugin-unused-imports: 2.0.0_eslint@8.36.0 - magic-string: 0.27.0 - postcss: 8.4.20 - rollup: 3.9.1 - rollup-plugin-polyfill-node: 0.11.0_rollup@3.9.1 - rollup-plugin-postcss: 4.0.2_postcss@8.4.20 - rollup-plugin-ts: 3.0.2_tumybvdr6br7dr3yffpdihdhou - vite: 4.2.1_@types+node@18.15.5 - vite-plugin-fonts: 0.7.0_vite@4.2.1 + dependencies: + '@esbuild-plugins/node-globals-polyfill': + specifier: ^0.1.1 + version: 0.1.1(esbuild@0.17.12) + '@eslint/eslintrc': + specifier: ^1.4.1 + version: 1.4.1 + '@rollup/plugin-commonjs': + specifier: ^24.0.0 + version: 24.0.0(rollup@3.9.1) + '@rollup/plugin-node-resolve': + specifier: ^15.0.1 + version: 15.0.1(rollup@3.9.1) + '@types/rollup-plugin-polyfill-node': + specifier: workspace:* + version: link:../../@types/rollup-plugin-polyfill-node + '@types/rollup__plugin-commonjs': + specifier: workspace:^ + version: link:../../@types/@rollup/plugin-commonjs + '@types/rollup__plugin-node-resolve': + specifier: workspace:^ + version: link:../../@types/@rollup/plugin-node-resolve + '@typescript-eslint/parser': + specifier: ^5.56.0 + version: 5.56.0(eslint@8.36.0)(typescript@5.0.2) + eslint: + specifier: ^8.36.0 + version: 8.36.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.36.0) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint@8.36.0) + eslint-plugin-json: + specifier: ^3.1.0 + version: 3.1.0 + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.6) + eslint-plugin-simple-import-sort: + specifier: ^10.0.0 + version: 10.0.0(eslint@8.36.0) + eslint-plugin-unused-imports: + specifier: ^2.0.0 + version: 2.0.0(eslint@8.36.0) + magic-string: + specifier: ^0.27.0 + version: 0.27.0 + postcss: + specifier: ^8.4.20 + version: 8.4.20 + rollup: + specifier: ^3.9.1 + version: 3.9.1 + rollup-plugin-polyfill-node: + specifier: ^0.11.0 + version: 0.11.0(rollup@3.9.1) + rollup-plugin-postcss: + specifier: ^4.0.2 + version: 4.0.2(postcss@8.4.20) + rollup-plugin-ts: + specifier: '*' + version: 3.0.2(rollup@3.9.1)(typescript@5.0.2) + vite: + specifier: 4.2.1 + version: 4.2.1(@types/node@18.15.5) + vite-plugin-fonts: + specifier: 0.7.0 + version: 0.7.0(vite@4.2.1) devDependencies: - '@types/node': 18.15.5 - typescript: 5.0.2 + '@types/node': + specifier: 18.15.5 + version: 18.15.5 + typescript: + specifier: ^5.0.2 + version: 5.0.2 workspace/eslint: - specifiers: - '@types/eslint': ^8.21.3 - '@types/node': 18.15.5 - '@typescript-eslint/eslint-plugin': ^5.56.0 - '@typescript-eslint/parser': ^5.56.0 - eslint: ^8.26.0 - eslint-config-prettier: ^8.8.0 - eslint-import-resolver-typescript: ^3.5.3 - eslint-plugin-import: ^2.27.5 - eslint-plugin-json: ^3.1.0 - eslint-plugin-jsonc: ^2.7.0 - eslint-plugin-prettier: ^4.2.1 - eslint-plugin-simple-import-sort: ^10.0.0 - eslint-plugin-unused-imports: ^2.0.0 - jsonc-eslint-parser: ^2.1.0 - prettier: ^2.8.6 - typescript: '*' dependencies: - '@types/eslint': 8.21.3 - '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu - eslint: 8.36.0 - eslint-config-prettier: 8.8.0_eslint@8.36.0 - eslint-import-resolver-typescript: 3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy - eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq - eslint-plugin-json: 3.1.0 - eslint-plugin-jsonc: 2.7.0_eslint@8.36.0 - eslint-plugin-prettier: 4.2.1_ose2zoovovx4ulolhifz3tfzx4 - eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0 - eslint-plugin-unused-imports: 2.0.0_pjgbsoxltfjhart6hcjsvw66hu - jsonc-eslint-parser: 2.1.0 - prettier: 2.8.6 - typescript: 5.0.2 + '@types/eslint': + specifier: ^8.21.3 + version: 8.21.3 + '@typescript-eslint/eslint-plugin': + specifier: ^5.56.0 + version: 5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2) + '@typescript-eslint/parser': + specifier: ^5.56.0 + version: 5.56.0(eslint@8.36.0)(typescript@5.0.2) + eslint: + specifier: ^8.26.0 + version: 8.36.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.36.0) + eslint-import-resolver-typescript: + specifier: ^3.5.3 + version: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint-plugin-json: + specifier: ^3.1.0 + version: 3.1.0 + eslint-plugin-jsonc: + specifier: ^2.7.0 + version: 2.7.0(eslint@8.36.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.6) + eslint-plugin-simple-import-sort: + specifier: ^10.0.0 + version: 10.0.0(eslint@8.36.0) + eslint-plugin-unused-imports: + specifier: ^2.0.0 + version: 2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0) + jsonc-eslint-parser: + specifier: ^2.1.0 + version: 2.1.0 + prettier: + specifier: ^2.8.6 + version: 2.8.6 + typescript: + specifier: '*' + version: 5.0.2 devDependencies: - '@types/node': 18.15.5 + '@types/node': + specifier: 18.15.5 + version: 18.15.5 workspace/json: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@types/shell-escape-tag': workspace:^ - shell-escape-tag: ^2.0.2 dependencies: - shell-escape-tag: 2.0.2 + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 devDependencies: - '@starbeam-dev/build-support': link:../build - '@types/shell-escape-tag': link:../../@types/shell-escape-tag + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag workspace/package: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/json': workspace:^ - '@starbeam-workspace/paths': workspace:^ - '@starbeam-workspace/reporter': workspace:^ - '@starbeam-workspace/shared': workspace:^ - '@types/shell-escape-tag': workspace:^ - shell-escape-tag: ^2.0.2 - dependencies: - '@starbeam-workspace/json': link:../json - '@starbeam-workspace/paths': link:../paths - '@starbeam-workspace/reporter': link:../reporter - '@starbeam-workspace/shared': link:../shared - shell-escape-tag: 2.0.2 + dependencies: + '@starbeam-workspace/json': + specifier: workspace:^ + version: link:../json + '@starbeam-workspace/paths': + specifier: workspace:^ + version: link:../paths + '@starbeam-workspace/reporter': + specifier: workspace:^ + version: link:../reporter + '@starbeam-workspace/shared': + specifier: workspace:^ + version: link:../shared + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 devDependencies: - '@starbeam-dev/build-support': link:../build - '@types/shell-escape-tag': link:../../@types/shell-escape-tag + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag workspace/paths: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/json': workspace:* - '@types/shell-escape-tag': workspace:^ - shell-escape-tag: ^2.0.2 - dependencies: - '@starbeam-workspace/json': link:../json - shell-escape-tag: 2.0.2 + dependencies: + '@starbeam-workspace/json': + specifier: workspace:* + version: link:../json + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 devDependencies: - '@starbeam-dev/build-support': link:../build - '@types/shell-escape-tag': link:../../@types/shell-escape-tag + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag workspace/reporter: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/paths': workspace:^ - '@starbeam-workspace/shared': workspace:^ - '@starbeam/core-utils': workspace:^ - '@types/node': 18.15.5 - '@types/shell-escape-tag': workspace:^ - '@types/shell-split': workspace:^ - '@types/split2': ^3.2.1 - '@types/wrap-ansi': ^8.0.1 - ansicolor: ^1.1.100 - chalk: ^5.2.0 - cli-table3: ^0.6.3 - emoji-regex: ^10.2.1 - node-pty: ^0.10.1 - shell-escape-tag: ^2.0.2 - shell-split: ^1.0.0 - split2: ^4.1.0 - wrap-ansi: ^8.0.1 - dependencies: - '@starbeam-workspace/paths': link:../paths - '@starbeam-workspace/shared': link:../shared - '@starbeam/core-utils': link:../../packages/universal/core-utils - ansicolor: 1.1.100 - chalk: 5.2.0 - cli-table3: 0.6.3 - emoji-regex: 10.2.1 - node-pty: 0.10.1 - shell-escape-tag: 2.0.2 - shell-split: 1.0.0 - split2: 4.1.0 - wrap-ansi: 8.0.1 + dependencies: + '@starbeam-workspace/paths': + specifier: workspace:^ + version: link:../paths + '@starbeam-workspace/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../../packages/universal/core-utils + ansicolor: + specifier: ^1.1.100 + version: 1.1.100 + chalk: + specifier: ^5.2.0 + version: 5.2.0 + cli-table3: + specifier: ^0.6.3 + version: 0.6.3 + emoji-regex: + specifier: ^10.2.1 + version: 10.2.1 + node-pty: + specifier: ^0.10.1 + version: 0.10.1 + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 + shell-split: + specifier: ^1.0.0 + version: 1.0.0 + split2: + specifier: ^4.1.0 + version: 4.1.0 + wrap-ansi: + specifier: ^8.0.1 + version: 8.0.1 devDependencies: - '@starbeam-dev/build-support': link:../build - '@types/node': 18.15.5 - '@types/shell-escape-tag': link:../../@types/shell-escape-tag - '@types/shell-split': link:../../@types/shell-split - '@types/split2': 3.2.1 - '@types/wrap-ansi': 8.0.1 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + '@types/node': + specifier: 18.15.5 + version: 18.15.5 + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag + '@types/shell-split': + specifier: workspace:^ + version: link:../../@types/shell-split + '@types/split2': + specifier: ^3.2.1 + version: 3.2.1 + '@types/wrap-ansi': + specifier: ^8.0.1 + version: 8.0.1 workspace/scripts: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/json': workspace:* - '@starbeam-workspace/package': workspace:* - '@starbeam-workspace/paths': workspace:* - '@starbeam-workspace/reporter': workspace:* - '@starbeam-workspace/shared': workspace:* - '@starbeam-workspace/workspace': workspace:* - '@types/prettier': ^2.7.2 - '@types/shell-escape-tag': workspace:^ - '@types/shell-split': workspace:^ - '@types/shelljs': ^0.8.11 - '@types/split2': ^3.2.1 - '@types/wrap-ansi': ^8.0.1 - ansicolor: ^1.1.100 - chalk: ^5.2.0 - cli-table3: ^0.6.3 - commander: ^9.3.0 - depcheck: ^1.4.3 - dirfilename: ^1.0.4 - emoji-regex: ^10.2.1 - eslint: ^8.36.0 - esno: ^0.16.3 - fast-glob: ^3.2.11 - jsonc-parser: ^3.0.0 - node-pty: ^0.10.1 - prettier: ^2.8.1 - shell-escape-tag: ^2.0.2 - shell-split: ^1.0.0 - shelljs: ^0.8.5 - split2: ^4.1.0 - term-size: ^3.0.2 - wrap-ansi: ^8.0.1 - dependencies: - '@starbeam-workspace/json': link:../json - '@starbeam-workspace/package': link:../package - '@starbeam-workspace/paths': link:../paths - '@starbeam-workspace/reporter': link:../reporter - '@starbeam-workspace/shared': link:../shared - '@starbeam-workspace/workspace': link:../workspace - ansicolor: 1.1.100 - chalk: 5.2.0 - commander: 9.4.1 - depcheck: 1.4.3 - dirfilename: 1.1.1 - emoji-regex: 10.2.1 - eslint: 8.36.0 - fast-glob: 3.2.12 - node-pty: 0.10.1 - prettier: 2.8.1 - shell-escape-tag: 2.0.2 - shell-split: 1.0.0 - shelljs: 0.8.5 - split2: 4.1.0 + dependencies: + '@starbeam-workspace/json': + specifier: workspace:* + version: link:../json + '@starbeam-workspace/package': + specifier: workspace:* + version: link:../package + '@starbeam-workspace/paths': + specifier: workspace:* + version: link:../paths + '@starbeam-workspace/reporter': + specifier: workspace:* + version: link:../reporter + '@starbeam-workspace/shared': + specifier: workspace:* + version: link:../shared + '@starbeam-workspace/workspace': + specifier: workspace:* + version: link:../workspace + ansicolor: + specifier: ^1.1.100 + version: 1.1.100 + chalk: + specifier: ^5.2.0 + version: 5.2.0 + commander: + specifier: ^9.3.0 + version: 9.4.1 + depcheck: + specifier: ^1.4.3 + version: 1.4.3 + dirfilename: + specifier: ^1.0.4 + version: 1.1.1 + emoji-regex: + specifier: ^10.2.1 + version: 10.2.1 + eslint: + specifier: ^8.36.0 + version: 8.36.0 + fast-glob: + specifier: ^3.2.11 + version: 3.2.12 + node-pty: + specifier: ^0.10.1 + version: 0.10.1 + prettier: + specifier: ^2.8.1 + version: 2.8.1 + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 + shell-split: + specifier: ^1.0.0 + version: 1.0.0 + shelljs: + specifier: ^0.8.5 + version: 0.8.5 + split2: + specifier: ^4.1.0 + version: 4.1.0 devDependencies: - '@starbeam-dev/build-support': link:../build - '@types/prettier': 2.7.2 - '@types/shell-escape-tag': link:../../@types/shell-escape-tag - '@types/shell-split': link:../../@types/shell-split - '@types/shelljs': 0.8.11 - '@types/split2': 3.2.1 - '@types/wrap-ansi': 8.0.1 - cli-table3: 0.6.3 - esno: 0.16.3 - jsonc-parser: 3.2.0 - term-size: 3.0.2 - wrap-ansi: 8.0.1 + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + '@types/prettier': + specifier: ^2.7.2 + version: 2.7.2 + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag + '@types/shell-split': + specifier: workspace:^ + version: link:../../@types/shell-split + '@types/shelljs': + specifier: ^0.8.11 + version: 0.8.11 + '@types/split2': + specifier: ^3.2.1 + version: 3.2.1 + '@types/wrap-ansi': + specifier: ^8.0.1 + version: 8.0.1 + cli-table3: + specifier: ^0.6.3 + version: 0.6.3 + esno: + specifier: ^0.16.3 + version: 0.16.3 + jsonc-parser: + specifier: ^3.0.0 + version: 3.2.0 + term-size: + specifier: ^3.0.2 + version: 3.0.2 + wrap-ansi: + specifier: ^8.0.1 + version: 8.0.1 workspace/shared: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/json': workspace:^ - '@types/shell-escape-tag': workspace:^ - shell-escape-tag: ^2.0.2 - term-size: ^3.0.2 - dependencies: - '@starbeam-workspace/json': link:../json - shell-escape-tag: 2.0.2 - term-size: 3.0.2 + dependencies: + '@starbeam-workspace/json': + specifier: workspace:^ + version: link:../json + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 + term-size: + specifier: ^3.0.2 + version: 3.0.2 devDependencies: - '@starbeam-dev/build-support': link:../build - '@types/shell-escape-tag': link:../../@types/shell-escape-tag + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag workspace/workspace: - specifiers: - '@starbeam-dev/build-support': workspace:* - '@starbeam-workspace/paths': workspace:^ - '@starbeam-workspace/reporter': workspace:^ - '@types/shell-escape-tag': workspace:^ - child_process: ^1.0.2 - shell-escape-tag: ^2.0.2 - dependencies: - '@starbeam-workspace/paths': link:../paths - '@starbeam-workspace/reporter': link:../reporter - '@types/shell-escape-tag': link:../../@types/shell-escape-tag - child_process: 1.0.2 - shell-escape-tag: 2.0.2 + dependencies: + '@starbeam-workspace/paths': + specifier: workspace:^ + version: link:../paths + '@starbeam-workspace/reporter': + specifier: workspace:^ + version: link:../reporter + '@types/shell-escape-tag': + specifier: workspace:^ + version: link:../../@types/shell-escape-tag + child_process: + specifier: ^1.0.2 + version: 1.0.2 + shell-escape-tag: + specifier: ^2.0.2 + version: 2.0.2 devDependencies: - '@starbeam-dev/build-support': link:../build + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build packages: - /@ampproject/remapping/2.2.0: + /@ampproject/remapping@2.2.0: resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} engines: {node: '>=6.0.0'} dependencies: @@ -1354,30 +1851,30 @@ packages: '@jridgewell/trace-mapping': 0.3.17 dev: true - /@babel/code-frame/7.18.6: + /@babel/code-frame@7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/highlight': 7.18.6 - /@babel/compat-data/7.20.1: + /@babel/compat-data@7.20.1: resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==} engines: {node: '>=6.9.0'} dev: true - /@babel/compat-data/7.21.0: + /@babel/compat-data@7.21.0: resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} engines: {node: '>=6.9.0'} dev: true - /@babel/core/7.21.3: + /@babel/core@7.21.3: resolution: {integrity: sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.0 '@babel/code-frame': 7.18.6 '@babel/generator': 7.21.3 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.21.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) '@babel/helper-module-transforms': 7.21.2 '@babel/helpers': 7.21.0 '@babel/parser': 7.21.3 @@ -1393,7 +1890,7 @@ packages: - supports-color dev: true - /@babel/eslint-parser/7.21.3_pxuto7xgangxlusvzceggvrmde: + /@babel/eslint-parser@7.21.3(@babel/core@7.21.3)(eslint@8.36.0): resolution: {integrity: sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: @@ -1407,7 +1904,7 @@ packages: semver: 6.3.0 dev: true - /@babel/generator/7.20.4: + /@babel/generator@7.20.4: resolution: {integrity: sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==} engines: {node: '>=6.9.0'} dependencies: @@ -1415,7 +1912,7 @@ packages: '@jridgewell/gen-mapping': 0.3.2 jsesc: 2.5.2 - /@babel/generator/7.20.7: + /@babel/generator@7.20.7: resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} engines: {node: '>=6.9.0'} dependencies: @@ -1424,7 +1921,7 @@ packages: jsesc: 2.5.2 dev: true - /@babel/generator/7.21.3: + /@babel/generator@7.21.3: resolution: {integrity: sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==} engines: {node: '>=6.9.0'} dependencies: @@ -1434,14 +1931,14 @@ packages: jsesc: 2.5.2 dev: true - /@babel/helper-annotate-as-pure/7.18.6: + /@babel/helper-annotate-as-pure@7.18.6: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 dev: true - /@babel/helper-builder-binary-assignment-operator-visitor/7.18.9: + /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} engines: {node: '>=6.9.0'} dependencies: @@ -1449,7 +1946,7 @@ packages: '@babel/types': 7.20.7 dev: true - /@babel/helper-compilation-targets/7.20.0_@babel+core@7.21.3: + /@babel/helper-compilation-targets@7.20.0(@babel/core@7.21.3): resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1462,7 +1959,7 @@ packages: semver: 6.3.0 dev: true - /@babel/helper-compilation-targets/7.20.7_@babel+core@7.21.3: + /@babel/helper-compilation-targets@7.20.7(@babel/core@7.21.3): resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1476,7 +1973,7 @@ packages: semver: 6.3.0 dev: true - /@babel/helper-create-class-features-plugin/7.20.7_@babel+core@7.21.3: + /@babel/helper-create-class-features-plugin@7.20.7(@babel/core@7.21.3): resolution: {integrity: sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1494,7 +1991,7 @@ packages: - supports-color dev: true - /@babel/helper-create-class-features-plugin/7.21.0_@babel+core@7.21.3: + /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1513,7 +2010,7 @@ packages: - supports-color dev: true - /@babel/helper-create-regexp-features-plugin/7.19.0_@babel+core@7.21.3: + /@babel/helper-create-regexp-features-plugin@7.19.0(@babel/core@7.21.3): resolution: {integrity: sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1524,13 +2021,13 @@ packages: regexpu-core: 5.2.1 dev: true - /@babel/helper-define-polyfill-provider/0.3.3_@babel+core@7.21.3: + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.3): resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 + '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 debug: 4.3.4 lodash.debounce: 4.0.8 @@ -1540,25 +2037,25 @@ packages: - supports-color dev: true - /@babel/helper-environment-visitor/7.18.9: + /@babel/helper-environment-visitor@7.18.9: resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} engines: {node: '>=6.9.0'} - /@babel/helper-explode-assignable-expression/7.18.6: + /@babel/helper-explode-assignable-expression@7.18.6: resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 dev: true - /@babel/helper-function-name/7.19.0: + /@babel/helper-function-name@7.19.0: resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 '@babel/types': 7.20.7 - /@babel/helper-function-name/7.21.0: + /@babel/helper-function-name@7.21.0: resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} engines: {node: '>=6.9.0'} dependencies: @@ -1566,34 +2063,34 @@ packages: '@babel/types': 7.21.3 dev: true - /@babel/helper-hoist-variables/7.18.6: + /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - /@babel/helper-member-expression-to-functions/7.20.7: + /@babel/helper-member-expression-to-functions@7.20.7: resolution: {integrity: sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 dev: true - /@babel/helper-member-expression-to-functions/7.21.0: + /@babel/helper-member-expression-to-functions@7.21.0: resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 dev: true - /@babel/helper-module-imports/7.18.6: + /@babel/helper-module-imports@7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 dev: true - /@babel/helper-module-transforms/7.20.2: + /@babel/helper-module-transforms@7.20.2: resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} engines: {node: '>=6.9.0'} dependencies: @@ -1609,7 +2106,7 @@ packages: - supports-color dev: true - /@babel/helper-module-transforms/7.21.2: + /@babel/helper-module-transforms@7.21.2: resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} engines: {node: '>=6.9.0'} dependencies: @@ -1625,19 +2122,19 @@ packages: - supports-color dev: true - /@babel/helper-optimise-call-expression/7.18.6: + /@babel/helper-optimise-call-expression@7.18.6: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 dev: true - /@babel/helper-plugin-utils/7.20.2: + /@babel/helper-plugin-utils@7.20.2: resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.21.3: + /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1652,7 +2149,7 @@ packages: - supports-color dev: true - /@babel/helper-replace-supers/7.20.7: + /@babel/helper-replace-supers@7.20.7: resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} engines: {node: '>=6.9.0'} dependencies: @@ -1666,45 +2163,45 @@ packages: - supports-color dev: true - /@babel/helper-simple-access/7.20.2: + /@babel/helper-simple-access@7.20.2: resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 dev: true - /@babel/helper-skip-transparent-expression-wrappers/7.20.0: + /@babel/helper-skip-transparent-expression-wrappers@7.20.0: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 dev: true - /@babel/helper-split-export-declaration/7.18.6: + /@babel/helper-split-export-declaration@7.18.6: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - /@babel/helper-string-parser/7.19.4: + /@babel/helper-string-parser@7.19.4: resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.19.1: + /@babel/helper-validator-identifier@7.19.1: resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option/7.18.6: + /@babel/helper-validator-option@7.18.6: resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-validator-option/7.21.0: + /@babel/helper-validator-option@7.21.0: resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-wrap-function/7.19.0: + /@babel/helper-wrap-function@7.19.0: resolution: {integrity: sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==} engines: {node: '>=6.9.0'} dependencies: @@ -1716,7 +2213,7 @@ packages: - supports-color dev: true - /@babel/helpers/7.21.0: + /@babel/helpers@7.21.0: resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} engines: {node: '>=6.9.0'} dependencies: @@ -1727,7 +2224,7 @@ packages: - supports-color dev: true - /@babel/highlight/7.18.6: + /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} dependencies: @@ -1735,7 +2232,7 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser/7.16.4: + /@babel/parser@7.16.4: resolution: {integrity: sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==} engines: {node: '>=6.0.0'} hasBin: true @@ -1743,21 +2240,21 @@ packages: '@babel/types': 7.20.2 dev: false - /@babel/parser/7.20.3: + /@babel/parser@7.20.3: resolution: {integrity: sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==} engines: {node: '>=6.0.0'} hasBin: true dependencies: '@babel/types': 7.21.3 - /@babel/parser/7.20.7: + /@babel/parser@7.20.7: resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} engines: {node: '>=6.0.0'} hasBin: true dependencies: '@babel/types': 7.21.3 - /@babel/parser/7.21.3: + /@babel/parser@7.21.3: resolution: {integrity: sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -1765,7 +2262,7 @@ packages: '@babel/types': 7.21.3 dev: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.21.3: + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1775,7 +2272,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.18.9_@babel+core@7.21.3: + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1784,10 +2281,10 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.21.3 + '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-async-generator-functions/7.20.1_@babel+core@7.21.3: + /@babel/plugin-proposal-async-generator-functions@7.20.1(@babel/core@7.21.3): resolution: {integrity: sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1796,56 +2293,56 @@ packages: '@babel/core': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.21.3 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-class-static-block@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.21.3 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-decorators/7.21.0_@babel+core@7.21.3: + /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.21.0_@babel+core@7.21.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/plugin-syntax-decorators': 7.21.0_@babel+core@7.21.3 + '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-dynamic-import/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1853,10 +2350,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.21.3: + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1864,10 +2361,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1875,10 +2372,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-logical-assignment-operators/7.18.9_@babel+core@7.21.3: + /@babel/plugin-proposal-logical-assignment-operators@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1886,10 +2383,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.21.3 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1897,10 +2394,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-numeric-separator/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1908,10 +2405,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.21.3 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-object-rest-spread/7.20.2_@babel+core@7.21.3: + /@babel/plugin-proposal-object-rest-spread@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1919,13 +2416,13 @@ packages: dependencies: '@babel/compat-data': 7.20.1 '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 + '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-transform-parameters': 7.20.3_@babel+core@7.21.3 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1933,10 +2430,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-optional-chaining/7.18.9_@babel+core@7.21.3: + /@babel/plugin-proposal-optional-chaining@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1945,23 +2442,23 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.21.3 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) dev: true - /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-property-in-object/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-private-property-in-object@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -1969,25 +2466,25 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.20.7_@babel+core@7.21.3 + '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.21.3 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.21.3: + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.21.3: + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.3): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1996,7 +2493,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.21.3: + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.3): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2005,7 +2502,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.21.3: + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.3): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2015,7 +2512,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-decorators/7.21.0_@babel+core@7.21.3: + /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2025,7 +2522,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2034,7 +2531,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2043,7 +2540,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.21.3: + /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.21.3): resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2053,7 +2550,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2062,7 +2559,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.21.3: + /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2072,7 +2569,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.21.3: + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.3): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2081,7 +2578,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2090,7 +2587,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.21.3: + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.3): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2099,7 +2596,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2108,7 +2605,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2117,7 +2614,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.21.3: + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2126,7 +2623,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.21.3: + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.3): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2136,7 +2633,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.21.3: + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.3): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2146,7 +2643,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.21.3: + /@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.21.3): resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2156,7 +2653,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-arrow-functions/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-arrow-functions@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2166,7 +2663,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-async-to-generator/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-async-to-generator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2175,12 +2672,12 @@ packages: '@babel/core': 7.21.3 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.21.3 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2190,7 +2687,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-block-scoping/7.20.2_@babel+core@7.21.3: + /@babel/plugin-transform-block-scoping@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2200,7 +2697,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-classes/7.20.2_@babel+core@7.21.3: + /@babel/plugin-transform-classes@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2208,7 +2705,7 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 + '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.19.0 '@babel/helper-optimise-call-expression': 7.18.6 @@ -2220,7 +2717,7 @@ packages: - supports-color dev: true - /@babel/plugin-transform-computed-properties/7.18.9_@babel+core@7.21.3: + /@babel/plugin-transform-computed-properties@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2230,7 +2727,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-destructuring/7.20.2_@babel+core@7.21.3: + /@babel/plugin-transform-destructuring@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2240,18 +2737,18 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.21.3: + /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2261,7 +2758,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2272,7 +2769,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-for-of/7.18.8_@babel+core@7.21.3: + /@babel/plugin-transform-for-of@7.18.8(@babel/core@7.21.3): resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2282,19 +2779,19 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.21.3: + /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 + '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-function-name': 7.19.0 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-literals/7.18.9_@babel+core@7.21.3: + /@babel/plugin-transform-literals@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2304,7 +2801,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2314,7 +2811,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-modules-amd/7.19.6_@babel+core@7.21.3: + /@babel/plugin-transform-modules-amd@7.19.6(@babel/core@7.21.3): resolution: {integrity: sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2327,7 +2824,7 @@ packages: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs/7.19.6_@babel+core@7.21.3: + /@babel/plugin-transform-modules-commonjs@7.19.6(@babel/core@7.21.3): resolution: {integrity: sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2341,7 +2838,7 @@ packages: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs/7.19.6_@babel+core@7.21.3: + /@babel/plugin-transform-modules-systemjs@7.19.6(@babel/core@7.21.3): resolution: {integrity: sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2356,7 +2853,7 @@ packages: - supports-color dev: true - /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2369,18 +2866,18 @@ packages: - supports-color dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.19.1_@babel+core@7.21.3: + /@babel/plugin-transform-named-capturing-groups-regex@7.19.1(@babel/core@7.21.3): resolution: {integrity: sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2390,7 +2887,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2403,7 +2900,7 @@ packages: - supports-color dev: true - /@babel/plugin-transform-parameters/7.20.3_@babel+core@7.21.3: + /@babel/plugin-transform-parameters@7.20.3(@babel/core@7.21.3): resolution: {integrity: sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2413,7 +2910,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2423,7 +2920,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-react-display-name/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2433,17 +2930,17 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-react-jsx-development@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.21.3 + '@babel/plugin-transform-react-jsx': 7.19.0(@babel/core@7.21.3) dev: true - /@babel/plugin-transform-react-jsx/7.19.0_@babel+core@7.21.3: + /@babel/plugin-transform-react-jsx@7.19.0(@babel/core@7.21.3): resolution: {integrity: sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2453,11 +2950,11 @@ packages: '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.21.3) '@babel/types': 7.20.2 dev: true - /@babel/plugin-transform-react-pure-annotations/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2468,7 +2965,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-regenerator/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-regenerator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2479,7 +2976,7 @@ packages: regenerator-transform: 0.15.0 dev: true - /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2489,7 +2986,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-runtime/7.21.0_@babel+core@7.21.3: + /@babel/plugin-transform-runtime@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2498,15 +2995,15 @@ packages: '@babel/core': 7.21.3 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.21.3 - babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.21.3 - babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.21.3 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.3) semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2516,7 +3013,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-spread/7.19.0_@babel+core@7.21.3: + /@babel/plugin-transform-spread@7.19.0(@babel/core@7.21.3): resolution: {integrity: sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2527,7 +3024,7 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 dev: true - /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2537,7 +3034,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.21.3: + /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2547,7 +3044,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.21.3: + /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2557,7 +3054,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-typescript/7.21.3_@babel+core@7.21.3: + /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.21.3): resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2565,14 +3062,14 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.21.0_@babel+core@7.21.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.21.3 + '@babel/plugin-syntax-typescript': 7.20.0(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.21.3: + /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.21.3): resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2582,18 +3079,18 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.21.3: + /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0_@babel+core@7.21.3 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/preset-env/7.20.2_@babel+core@7.21.3: + /@babel/preset-env@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2601,98 +3098,98 @@ packages: dependencies: '@babel/compat-data': 7.20.1 '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.21.3 + '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-proposal-async-generator-functions': 7.20.1_@babel+core@7.21.3 - '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-class-static-block': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-dynamic-import': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-export-namespace-from': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-proposal-json-strings': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-logical-assignment-operators': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-numeric-separator': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-object-rest-spread': 7.20.2_@babel+core@7.21.3 - '@babel/plugin-proposal-optional-catch-binding': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-optional-chaining': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-private-property-in-object': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.21.3 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.21.3 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.21.3 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-import-assertions': 7.20.0_@babel+core@7.21.3 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.21.3 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.21.3 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.21.3 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.21.3 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.21.3 - '@babel/plugin-transform-arrow-functions': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-async-to-generator': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-block-scoped-functions': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-block-scoping': 7.20.2_@babel+core@7.21.3 - '@babel/plugin-transform-classes': 7.20.2_@babel+core@7.21.3 - '@babel/plugin-transform-computed-properties': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-transform-destructuring': 7.20.2_@babel+core@7.21.3 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-duplicate-keys': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-transform-exponentiation-operator': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-for-of': 7.18.8_@babel+core@7.21.3 - '@babel/plugin-transform-function-name': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-transform-literals': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-transform-member-expression-literals': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-modules-amd': 7.19.6_@babel+core@7.21.3 - '@babel/plugin-transform-modules-commonjs': 7.19.6_@babel+core@7.21.3 - '@babel/plugin-transform-modules-systemjs': 7.19.6_@babel+core@7.21.3 - '@babel/plugin-transform-modules-umd': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1_@babel+core@7.21.3 - '@babel/plugin-transform-new-target': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-object-super': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-parameters': 7.20.3_@babel+core@7.21.3 - '@babel/plugin-transform-property-literals': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-regenerator': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-reserved-words': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-shorthand-properties': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-spread': 7.19.0_@babel+core@7.21.3 - '@babel/plugin-transform-sticky-regex': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-template-literals': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-transform-typeof-symbol': 7.18.9_@babel+core@7.21.3 - '@babel/plugin-transform-unicode-escapes': 7.18.10_@babel+core@7.21.3 - '@babel/plugin-transform-unicode-regex': 7.18.6_@babel+core@7.21.3 - '@babel/preset-modules': 0.1.5_@babel+core@7.21.3 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-async-generator-functions': 7.20.1(@babel/core@7.21.3) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-class-static-block': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-logical-assignment-operators': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-object-rest-spread': 7.20.2(@babel/core@7.21.3) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-private-property-in-object': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.3) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.21.3) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-transform-arrow-functions': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-async-to-generator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-block-scoping': 7.20.2(@babel/core@7.21.3) + '@babel/plugin-transform-classes': 7.20.2(@babel/core@7.21.3) + '@babel/plugin-transform-computed-properties': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-destructuring': 7.20.2(@babel/core@7.21.3) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-for-of': 7.18.8(@babel/core@7.21.3) + '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-modules-amd': 7.19.6(@babel/core@7.21.3) + '@babel/plugin-transform-modules-commonjs': 7.19.6(@babel/core@7.21.3) + '@babel/plugin-transform-modules-systemjs': 7.19.6(@babel/core@7.21.3) + '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1(@babel/core@7.21.3) + '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) + '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-regenerator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-spread': 7.19.0(@babel/core@7.21.3) + '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.21.3) + '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.21.3) + '@babel/preset-modules': 0.1.5(@babel/core@7.21.3) '@babel/types': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.21.3 - babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.21.3 - babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.21.3 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.3) core-js-compat: 3.26.0 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/preset-modules/0.1.5_@babel+core@7.21.3: + /@babel/preset-modules@0.1.5(@babel/core@7.21.3): resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) '@babel/types': 7.20.2 esutils: 2.0.3 dev: true - /@babel/preset-react/7.18.6_@babel+core@7.21.3: + /@babel/preset-react@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2701,13 +3198,13 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-react-display-name': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.21.3 - '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.21.3 - '@babel/plugin-transform-react-pure-annotations': 7.18.6_@babel+core@7.21.3 + '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-react-jsx': 7.19.0(@babel/core@7.21.3) + '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-react-pure-annotations': 7.18.6(@babel/core@7.21.3) dev: true - /@babel/preset-typescript/7.21.0_@babel+core@7.21.3: + /@babel/preset-typescript@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==} engines: {node: '>=6.9.0'} peerDependencies: @@ -2716,18 +3213,18 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-transform-typescript': 7.21.3_@babel+core@7.21.3 + '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /@babel/runtime/7.21.0: + /@babel/runtime@7.21.0: resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.11 - /@babel/template/7.20.7: + /@babel/template@7.20.7: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} dependencies: @@ -2735,7 +3232,7 @@ packages: '@babel/parser': 7.20.7 '@babel/types': 7.21.3 - /@babel/traverse/7.20.1: + /@babel/traverse@7.20.1: resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} engines: {node: '>=6.9.0'} dependencies: @@ -2753,43 +3250,43 @@ packages: - supports-color dev: false - /@babel/traverse/7.20.10: - resolution: {integrity: sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg==} + /@babel/traverse@7.20.1(supports-color@5.5.0): + resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.7 + '@babel/generator': 7.20.4 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.21.0 + '@babel/helper-function-name': 7.19.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.7 - '@babel/types': 7.21.3 - debug: 4.3.4 + '@babel/parser': 7.20.3 + '@babel/types': 7.20.2 + debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/traverse/7.20.1_supports-color@5.5.0: - resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} + /@babel/traverse@7.20.10: + resolution: {integrity: sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.4 + '@babel/generator': 7.20.7 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.3 - '@babel/types': 7.20.2 - debug: 4.3.4_supports-color@5.5.0 + '@babel/parser': 7.20.7 + '@babel/types': 7.21.3 + debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/traverse/7.21.3: + /@babel/traverse@7.21.3: resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} engines: {node: '>=6.9.0'} dependencies: @@ -2807,7 +3304,7 @@ packages: - supports-color dev: true - /@babel/types/7.20.2: + /@babel/types@7.20.2: resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==} engines: {node: '>=6.9.0'} dependencies: @@ -2815,7 +3312,7 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 - /@babel/types/7.20.7: + /@babel/types@7.20.7: resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} engines: {node: '>=6.9.0'} dependencies: @@ -2823,7 +3320,7 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 - /@babel/types/7.21.3: + /@babel/types@7.21.3: resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==} engines: {node: '>=6.9.0'} dependencies: @@ -2831,7 +3328,7 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 - /@changesets/apply-release-plan/6.1.3: + /@changesets/apply-release-plan@6.1.3: resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==} dependencies: '@babel/runtime': 7.21.0 @@ -2849,7 +3346,7 @@ packages: semver: 5.7.1 dev: true - /@changesets/assemble-release-plan/5.2.3: + /@changesets/assemble-release-plan@5.2.3: resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==} dependencies: '@babel/runtime': 7.21.0 @@ -2860,13 +3357,13 @@ packages: semver: 5.7.1 dev: true - /@changesets/changelog-git/0.1.14: + /@changesets/changelog-git@0.1.14: resolution: {integrity: sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==} dependencies: '@changesets/types': 5.2.1 dev: true - /@changesets/cli/2.26.1: + /@changesets/cli@2.26.1: resolution: {integrity: sha512-XnTa+b51vt057fyAudvDKGB0Sh72xutQZNAdXkCqPBKO2zvs2yYZx5hFZj1u9cbtpwM6Sxtcr02/FQJfZOzemQ==} hasBin: true dependencies: @@ -2905,7 +3402,7 @@ packages: tty-table: 4.1.6 dev: true - /@changesets/config/2.3.0: + /@changesets/config@2.3.0: resolution: {integrity: sha512-EgP/px6mhCx8QeaMAvWtRrgyxW08k/Bx2tpGT+M84jEdX37v3VKfh4Cz1BkwrYKuMV2HZKeHOh8sHvja/HcXfQ==} dependencies: '@changesets/errors': 0.1.4 @@ -2917,13 +3414,13 @@ packages: micromatch: 4.0.5 dev: true - /@changesets/errors/0.1.4: + /@changesets/errors@0.1.4: resolution: {integrity: sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==} dependencies: extendable-error: 0.1.7 dev: true - /@changesets/get-dependents-graph/1.3.5: + /@changesets/get-dependents-graph@1.3.5: resolution: {integrity: sha512-w1eEvnWlbVDIY8mWXqWuYE9oKhvIaBhzqzo4ITSJY9hgoqQ3RoBqwlcAzg11qHxv/b8ReDWnMrpjpKrW6m1ZTA==} dependencies: '@changesets/types': 5.2.1 @@ -2933,7 +3430,7 @@ packages: semver: 5.7.1 dev: true - /@changesets/get-release-plan/3.0.16: + /@changesets/get-release-plan@3.0.16: resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==} dependencies: '@babel/runtime': 7.21.0 @@ -2945,11 +3442,11 @@ packages: '@manypkg/get-packages': 1.1.3 dev: true - /@changesets/get-version-range-type/0.3.2: + /@changesets/get-version-range-type@0.3.2: resolution: {integrity: sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==} dev: true - /@changesets/git/2.0.0: + /@changesets/git@2.0.0: resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} dependencies: '@babel/runtime': 7.21.0 @@ -2961,20 +3458,20 @@ packages: spawndamnit: 2.0.0 dev: true - /@changesets/logger/0.0.5: + /@changesets/logger@0.0.5: resolution: {integrity: sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==} dependencies: chalk: 2.4.2 dev: true - /@changesets/parse/0.3.16: + /@changesets/parse@0.3.16: resolution: {integrity: sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==} dependencies: '@changesets/types': 5.2.1 js-yaml: 3.14.1 dev: true - /@changesets/pre/1.0.14: + /@changesets/pre@1.0.14: resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} dependencies: '@babel/runtime': 7.21.0 @@ -2984,7 +3481,7 @@ packages: fs-extra: 7.0.1 dev: true - /@changesets/read/0.5.9: + /@changesets/read@0.5.9: resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} dependencies: '@babel/runtime': 7.21.0 @@ -2997,15 +3494,15 @@ packages: p-filter: 2.1.0 dev: true - /@changesets/types/4.1.0: + /@changesets/types@4.1.0: resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} dev: true - /@changesets/types/5.2.1: + /@changesets/types@5.2.1: resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} dev: true - /@changesets/write/0.2.3: + /@changesets/write@0.2.3: resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} dependencies: '@babel/runtime': 7.21.0 @@ -3015,13 +3512,13 @@ packages: prettier: 2.8.6 dev: true - /@colors/colors/1.5.0: + /@colors/colors@1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} requiresBuild: true optional: true - /@crxjs/vite-plugin/2.0.0-beta.15: + /@crxjs/vite-plugin@2.0.0-beta.15: resolution: {integrity: sha512-3lDltBqr41BZpJRidbXnKiWwvvfpb8CQ0SKEBW1XsnKTzP9ZcJnZuSoTizBxd6Hx2VPrGFooPjuh+ohQ3QIoHg==} dependencies: '@rollup/pluginutils': 4.2.1 @@ -3043,78 +3540,78 @@ packages: - supports-color dev: true - /@emotion/is-prop-valid/1.2.0: + /@emotion/is-prop-valid@1.2.0: resolution: {integrity: sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==} dependencies: '@emotion/memoize': 0.8.0 dev: true - /@emotion/memoize/0.8.0: + /@emotion/memoize@0.8.0: resolution: {integrity: sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==} dev: true - /@emotion/stylis/0.8.5: + /@emotion/stylis@0.8.5: resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} dev: true - /@emotion/unitless/0.7.5: + /@emotion/unitless@0.7.5: resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} dev: true - /@esbuild-kit/cjs-loader/2.4.0: + /@esbuild-kit/cjs-loader@2.4.0: resolution: {integrity: sha512-DBBCiHPgL2B/elUpvCDhNHXnlZQ9sfO2uyt1OJyAXKT41beQEFY4OxZ6gwS+ZesRCbZ6JV8M7GEyOPkjv8kdIw==} dependencies: '@esbuild-kit/core-utils': 3.0.0 get-tsconfig: 4.2.0 dev: true - /@esbuild-kit/core-utils/3.0.0: + /@esbuild-kit/core-utils@3.0.0: resolution: {integrity: sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==} dependencies: esbuild: 0.15.13 source-map-support: 0.5.21 dev: true - /@esbuild-kit/esm-loader/2.5.0: + /@esbuild-kit/esm-loader@2.5.0: resolution: {integrity: sha512-ySs0qOsiwj+hsgZM9/MniGdvfa9/WzqfFuIia8/5gSUPeIQIX2/tG91QakxPFOR35VFiwTB7wCiHtiS6dc6SkA==} dependencies: '@esbuild-kit/core-utils': 3.0.0 get-tsconfig: 4.2.0 dev: true - /@esbuild-plugins/node-globals-polyfill/0.1.1_esbuild@0.17.12: + /@esbuild-plugins/node-globals-polyfill@0.1.1(esbuild@0.17.12): resolution: {integrity: sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==} peerDependencies: esbuild: '*' dependencies: esbuild: 0.17.12 - /@esbuild/android-arm/0.15.13: - resolution: {integrity: sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==} + /@esbuild/android-arm64@0.17.12: + resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} engines: {node: '>=12'} - cpu: [arm] + cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true - /@esbuild/android-arm/0.17.12: - resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==} + /@esbuild/android-arm@0.15.13: + resolution: {integrity: sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==} engines: {node: '>=12'} cpu: [arm] os: [android] requiresBuild: true + dev: true optional: true - /@esbuild/android-arm64/0.17.12: - resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} + /@esbuild/android-arm@0.17.12: + resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [arm] os: [android] requiresBuild: true optional: true - /@esbuild/android-x64/0.17.12: + /@esbuild/android-x64@0.17.12: resolution: {integrity: sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==} engines: {node: '>=12'} cpu: [x64] @@ -3122,7 +3619,7 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-arm64/0.17.12: + /@esbuild/darwin-arm64@0.17.12: resolution: {integrity: sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==} engines: {node: '>=12'} cpu: [arm64] @@ -3130,7 +3627,7 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-x64/0.17.12: + /@esbuild/darwin-x64@0.17.12: resolution: {integrity: sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==} engines: {node: '>=12'} cpu: [x64] @@ -3138,7 +3635,7 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-arm64/0.17.12: + /@esbuild/freebsd-arm64@0.17.12: resolution: {integrity: sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==} engines: {node: '>=12'} cpu: [arm64] @@ -3146,7 +3643,7 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-x64/0.17.12: + /@esbuild/freebsd-x64@0.17.12: resolution: {integrity: sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==} engines: {node: '>=12'} cpu: [x64] @@ -3154,23 +3651,23 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm/0.17.12: - resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==} + /@esbuild/linux-arm64@0.17.12: + resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==} engines: {node: '>=12'} - cpu: [arm] + cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm64/0.17.12: - resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==} + /@esbuild/linux-arm@0.17.12: + resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [arm] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ia32/0.17.12: + /@esbuild/linux-ia32@0.17.12: resolution: {integrity: sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==} engines: {node: '>=12'} cpu: [ia32] @@ -3178,7 +3675,7 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-loong64/0.15.13: + /@esbuild/linux-loong64@0.15.13: resolution: {integrity: sha512-+BoyIm4I8uJmH/QDIH0fu7MG0AEx9OXEDXnqptXCwKOlOqZiS4iraH1Nr7/ObLMokW3sOCeBNyD68ATcV9b9Ag==} engines: {node: '>=12'} cpu: [loong64] @@ -3187,7 +3684,7 @@ packages: dev: true optional: true - /@esbuild/linux-loong64/0.17.12: + /@esbuild/linux-loong64@0.17.12: resolution: {integrity: sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==} engines: {node: '>=12'} cpu: [loong64] @@ -3195,7 +3692,7 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-mips64el/0.17.12: + /@esbuild/linux-mips64el@0.17.12: resolution: {integrity: sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==} engines: {node: '>=12'} cpu: [mips64el] @@ -3203,7 +3700,7 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ppc64/0.17.12: + /@esbuild/linux-ppc64@0.17.12: resolution: {integrity: sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==} engines: {node: '>=12'} cpu: [ppc64] @@ -3211,7 +3708,7 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-riscv64/0.17.12: + /@esbuild/linux-riscv64@0.17.12: resolution: {integrity: sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==} engines: {node: '>=12'} cpu: [riscv64] @@ -3219,7 +3716,7 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-s390x/0.17.12: + /@esbuild/linux-s390x@0.17.12: resolution: {integrity: sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==} engines: {node: '>=12'} cpu: [s390x] @@ -3227,7 +3724,7 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-x64/0.17.12: + /@esbuild/linux-x64@0.17.12: resolution: {integrity: sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==} engines: {node: '>=12'} cpu: [x64] @@ -3235,7 +3732,7 @@ packages: requiresBuild: true optional: true - /@esbuild/netbsd-x64/0.17.12: + /@esbuild/netbsd-x64@0.17.12: resolution: {integrity: sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==} engines: {node: '>=12'} cpu: [x64] @@ -3243,7 +3740,7 @@ packages: requiresBuild: true optional: true - /@esbuild/openbsd-x64/0.17.12: + /@esbuild/openbsd-x64@0.17.12: resolution: {integrity: sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==} engines: {node: '>=12'} cpu: [x64] @@ -3251,7 +3748,7 @@ packages: requiresBuild: true optional: true - /@esbuild/sunos-x64/0.17.12: + /@esbuild/sunos-x64@0.17.12: resolution: {integrity: sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==} engines: {node: '>=12'} cpu: [x64] @@ -3259,7 +3756,7 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-arm64/0.17.12: + /@esbuild/win32-arm64@0.17.12: resolution: {integrity: sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==} engines: {node: '>=12'} cpu: [arm64] @@ -3267,7 +3764,7 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-ia32/0.17.12: + /@esbuild/win32-ia32@0.17.12: resolution: {integrity: sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==} engines: {node: '>=12'} cpu: [ia32] @@ -3275,7 +3772,7 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-x64/0.17.12: + /@esbuild/win32-x64@0.17.12: resolution: {integrity: sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==} engines: {node: '>=12'} cpu: [x64] @@ -3283,7 +3780,7 @@ packages: requiresBuild: true optional: true - /@eslint-community/eslint-utils/4.3.0_eslint@8.36.0: + /@eslint-community/eslint-utils@4.3.0(eslint@8.36.0): resolution: {integrity: sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3292,11 +3789,11 @@ packages: eslint: 8.36.0 eslint-visitor-keys: 3.3.0 - /@eslint-community/regexpp/4.4.0: + /@eslint-community/regexpp@4.4.0: resolution: {integrity: sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - /@eslint/eslintrc/1.4.1: + /@eslint/eslintrc@1.4.1: resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: @@ -3313,7 +3810,7 @@ packages: - supports-color dev: false - /@eslint/eslintrc/2.0.1: + /@eslint/eslintrc@2.0.1: resolution: {integrity: sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: @@ -3329,16 +3826,16 @@ packages: transitivePeerDependencies: - supports-color - /@eslint/js/8.36.0: + /@eslint/js@8.36.0: resolution: {integrity: sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@faker-js/faker/7.6.0: + /@faker-js/faker@7.6.0: resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} engines: {node: '>=14.0.0', npm: '>=6.0.0'} dev: false - /@humanwhocodes/config-array/0.11.8: + /@humanwhocodes/config-array@0.11.8: resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} engines: {node: '>=10.10.0'} dependencies: @@ -3348,14 +3845,14 @@ packages: transitivePeerDependencies: - supports-color - /@humanwhocodes/module-importer/1.0.1: + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - /@humanwhocodes/object-schema/1.2.1: + /@humanwhocodes/object-schema@1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - /@jridgewell/gen-mapping/0.1.1: + /@jridgewell/gen-mapping@0.1.1: resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} engines: {node: '>=6.0.0'} dependencies: @@ -3363,7 +3860,7 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true - /@jridgewell/gen-mapping/0.3.2: + /@jridgewell/gen-mapping@0.3.2: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} engines: {node: '>=6.0.0'} dependencies: @@ -3371,24 +3868,24 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/trace-mapping': 0.3.17 - /@jridgewell/resolve-uri/3.1.0: + /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} - /@jridgewell/set-array/1.1.2: + /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} - /@jridgewell/sourcemap-codec/1.4.14: + /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - /@jridgewell/trace-mapping/0.3.17: + /@jridgewell/trace-mapping@0.3.17: resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - /@manypkg/find-root/1.1.0: + /@manypkg/find-root@1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: '@babel/runtime': 7.21.0 @@ -3397,7 +3894,7 @@ packages: fs-extra: 8.1.0 dev: true - /@manypkg/get-packages/1.1.3: + /@manypkg/get-packages@1.1.3: resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} dependencies: '@babel/runtime': 7.21.0 @@ -3408,35 +3905,35 @@ packages: read-yaml-file: 1.1.0 dev: true - /@mdn/browser-compat-data/4.2.1: + /@mdn/browser-compat-data@4.2.1: resolution: {integrity: sha512-EWUguj2kd7ldmrF9F+vI5hUOralPd+sdsUnYbRy33vZTuZkduC1shE9TtEMEjAQwyfyMb4ole5KtjF8MsnQOlA==} dev: false - /@nicolo-ribaudo/eslint-scope-5-internals/5.1.1-v1: + /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} dependencies: eslint-scope: 5.1.1 dev: true - /@nodelib/fs.scandir/2.1.5: + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - /@nodelib/fs.stat/2.0.5: + /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - /@nodelib/fs.walk/1.2.8: + /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.13.0 - /@pkgr/utils/2.3.1: + /@pkgr/utils@2.3.1: resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dependencies: @@ -3447,11 +3944,11 @@ packages: tiny-glob: 0.2.9 tslib: 2.5.0 - /@polka/url/1.0.0-next.21: + /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true - /@rollup/plugin-commonjs/24.0.0: + /@rollup/plugin-commonjs@24.0.0: resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3468,7 +3965,7 @@ packages: magic-string: 0.27.0 dev: false - /@rollup/plugin-commonjs/24.0.0_rollup@3.9.1: + /@rollup/plugin-commonjs@24.0.0(rollup@3.9.1): resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3477,7 +3974,7 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.9.1 + '@rollup/pluginutils': 5.0.2(rollup@3.9.1) commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.0.3 @@ -3486,7 +3983,7 @@ packages: rollup: 3.9.1 dev: false - /@rollup/plugin-inject/5.0.2_rollup@3.9.1: + /@rollup/plugin-inject@5.0.2(rollup@3.9.1): resolution: {integrity: sha512-zRthPC/sZ2OaQwPh2LvFn0A+3SyMAZR1Vqsp89mWkIuGXKswT8ty1JWj1pf7xdZvft4gHZaCuhdopuiCwjclWg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3495,13 +3992,13 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.9.1 + '@rollup/pluginutils': 5.0.2(rollup@3.9.1) estree-walker: 2.0.2 magic-string: 0.26.7 rollup: 3.9.1 dev: false - /@rollup/plugin-node-resolve/15.0.1: + /@rollup/plugin-node-resolve@15.0.1: resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3518,7 +4015,7 @@ packages: resolve: 1.22.1 dev: false - /@rollup/plugin-node-resolve/15.0.1_rollup@3.9.1: + /@rollup/plugin-node-resolve@15.0.1(rollup@3.9.1): resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3527,7 +4024,7 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.9.1 + '@rollup/pluginutils': 5.0.2(rollup@3.9.1) '@types/resolve': 1.20.2 deepmerge: 4.2.2 is-builtin-module: 3.2.0 @@ -3536,14 +4033,14 @@ packages: rollup: 3.9.1 dev: false - /@rollup/pluginutils/4.2.1: + /@rollup/pluginutils@4.2.1: resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} dependencies: estree-walker: 2.0.2 picomatch: 2.3.1 - /@rollup/pluginutils/5.0.2: + /@rollup/pluginutils@5.0.2: resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3557,7 +4054,7 @@ packages: picomatch: 2.3.1 dev: false - /@rollup/pluginutils/5.0.2_rollup@3.9.1: + /@rollup/pluginutils@5.0.2(rollup@3.9.1): resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3572,15 +4069,15 @@ packages: rollup: 3.9.1 dev: false - /@shopify/polaris-icons/6.7.0: + /@shopify/polaris-icons@6.7.0: resolution: {integrity: sha512-4tlMQvZlaTvp4uYWo5zZq7NSvD1IIxS13/anRWXwcCD/HPLj7wnyYfwveHQOwo1iyrVV4Z2+hTJYTFVe3CBR0g==} dev: true - /@shopify/polaris-tokens/6.3.0: + /@shopify/polaris-tokens@6.3.0: resolution: {integrity: sha512-ZYcV/yzTDw/qizqb2zKYi0ryNTWg1fKs492sZajs5Rk6TdEYIJSuIHG4U1iP2RFadIFWyHu5ELC5UZWsUCxP9w==} dev: true - /@shopify/polaris/10.16.1_biqbaboplfbrettd7655fr4n2y: + /@shopify/polaris@10.16.1(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-eKkkZNMTMVz4yJiGTOtti2+hYuIEgixHd+3RIWZxm555PIIoNUMVrpI+Xb54KgJ+J3eskxYRXdD/E4+aukaWtA==} peerDependencies: react: '*' @@ -3592,12 +4089,12 @@ packages: '@types/react-dom': 18.0.10 '@types/react-transition-group': 4.4.5 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) react-fast-compare: 3.2.0 - react-transition-group: 4.4.5_biqbaboplfbrettd7655fr4n2y + react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: true - /@testing-library/dom/8.19.0: + /@testing-library/dom@8.19.0: resolution: {integrity: sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==} engines: {node: '>=12'} dependencies: @@ -3611,7 +4108,7 @@ packages: pretty-format: 27.5.1 dev: true - /@testing-library/dom/8.19.1: + /@testing-library/dom@8.19.1: resolution: {integrity: sha512-P6iIPyYQ+qH8CvGauAqanhVnjrnRe0IZFSYCeGkSRW9q3u8bdVn2NPI+lasFyVsEQn1J/IFmp5Aax41+dAP9wg==} engines: {node: '>=12'} dependencies: @@ -3625,7 +4122,7 @@ packages: pretty-format: 27.5.1 dev: false - /@testing-library/dom/9.0.1: + /@testing-library/dom@9.0.1: resolution: {integrity: sha512-fTOVsMY9QLFCCXRHG3Ese6cMH5qIWwSbgxZsgeF5TNsy81HKaZ4kgehnSF8FsR3OF+numlIV2YcU79MzbnhSig==} engines: {node: '>=14'} dependencies: @@ -3639,7 +4136,7 @@ packages: pretty-format: 27.5.1 dev: true - /@testing-library/preact/3.2.2_preact@10.11.3: + /@testing-library/preact@3.2.2(preact@10.11.3): resolution: {integrity: sha512-mMPEp/9TOOqf3QqDHY02ieGFfRbi8fAxZvRifn+vOzrdNcCR1zchwPA6BvqXG3wAweRan4QJioYgEc1cePeC3g==} engines: {node: '>= 12'} peerDependencies: @@ -3649,7 +4146,7 @@ packages: preact: 10.11.3 dev: false - /@testing-library/react/13.4.0_biqbaboplfbrettd7655fr4n2y: + /@testing-library/react@13.4.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==} engines: {node: '>=12'} peerDependencies: @@ -3660,10 +4157,10 @@ packages: '@testing-library/dom': 8.19.0 '@types/react-dom': 18.0.10 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: true - /@testing-library/react/14.0.0_biqbaboplfbrettd7655fr4n2y: + /@testing-library/react@14.0.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} engines: {node: '>=14'} peerDependencies: @@ -3674,122 +4171,122 @@ packages: '@testing-library/dom': 9.0.1 '@types/react-dom': 18.0.10 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: true - /@tootallnate/once/2.0.0: + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} - /@trysound/sax/0.2.0: + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} dev: false - /@types/aria-query/4.2.2: + /@types/aria-query@4.2.2: resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} dev: true - /@types/aria-query/5.0.1: + /@types/aria-query@5.0.1: resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} - /@types/chai-subset/1.3.3: + /@types/chai-subset@1.3.3: resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} dependencies: '@types/chai': 4.3.4 - /@types/chai/4.3.4: + /@types/chai@4.3.4: resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} - /@types/eslint/8.21.3: + /@types/eslint@8.21.3: resolution: {integrity: sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==} dependencies: '@types/estree': 1.0.0 '@types/json-schema': 7.0.11 - /@types/estree/1.0.0: + /@types/estree@1.0.0: resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} - /@types/glob/8.0.0: + /@types/glob@8.0.0: resolution: {integrity: sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==} dependencies: '@types/minimatch': 5.1.2 '@types/node': 18.15.5 dev: true - /@types/hoist-non-react-statics/3.3.1: + /@types/hoist-non-react-statics@3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: '@types/react': 18.0.28 hoist-non-react-statics: 3.3.2 dev: true - /@types/is-ci/3.0.0: + /@types/is-ci@3.0.0: resolution: {integrity: sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==} dependencies: ci-info: 3.5.0 dev: true - /@types/json-schema/7.0.11: + /@types/json-schema@7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - /@types/json5/0.0.29: + /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - /@types/minimatch/3.0.5: + /@types/minimatch@3.0.5: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} dev: false - /@types/minimatch/5.1.2: + /@types/minimatch@5.1.2: resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} dev: true - /@types/minimist/1.2.2: + /@types/minimist@1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node/18.15.5: + /@types/node@18.15.5: resolution: {integrity: sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==} - /@types/normalize-package-data/2.4.1: + /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true - /@types/object-path/0.11.1: + /@types/object-path@0.11.1: resolution: {integrity: sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg==} dev: false - /@types/parse-json/4.0.0: + /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: false - /@types/prettier/2.7.2: + /@types/prettier@2.7.2: resolution: {integrity: sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==} dev: true - /@types/prop-types/15.7.5: + /@types/prop-types@15.7.5: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} dev: true - /@types/react-dom/18.0.10: + /@types/react-dom@18.0.10: resolution: {integrity: sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==} dependencies: '@types/react': 18.0.26 dev: true - /@types/react-portal/4.0.4: + /@types/react-portal@4.0.4: resolution: {integrity: sha512-ecVWngYHeSymq5XdrQOXRpIb9ay5SM4Stm/ur6+wc0Z+r05gafZ5SuMRbXKYsj4exNJa+4CTKK6J7qcTKm9K5g==} dependencies: '@types/react': 18.0.26 dev: true - /@types/react-transition-group/4.4.5: + /@types/react-transition-group@4.4.5: resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==} dependencies: '@types/react': 18.0.28 dev: true - /@types/react/18.0.26: + /@types/react@18.0.26: resolution: {integrity: sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==} dependencies: '@types/prop-types': 15.7.5 @@ -3797,7 +4294,7 @@ packages: csstype: 3.1.1 dev: true - /@types/react/18.0.28: + /@types/react@18.0.28: resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==} dependencies: '@types/prop-types': 15.7.5 @@ -3805,35 +4302,35 @@ packages: csstype: 3.1.1 dev: true - /@types/resolve/1.20.2: + /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: false - /@types/scheduler/0.16.2: + /@types/scheduler@0.16.2: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} dev: true - /@types/semver/6.2.3: + /@types/semver@6.2.3: resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} dev: true - /@types/semver/7.3.13: + /@types/semver@7.3.13: resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} - /@types/shelljs/0.8.11: + /@types/shelljs@0.8.11: resolution: {integrity: sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==} dependencies: '@types/glob': 8.0.0 '@types/node': 18.15.5 dev: true - /@types/split2/3.2.1: + /@types/split2@3.2.1: resolution: {integrity: sha512-7uz3yU+LooBq4yNOzlZD9PU9/1Eu0rTD1MjQ6apOVEoHsPrMUrFw7W8XrvWtesm2vK67SBK9AyJcOXtMpl9bgQ==} dependencies: '@types/node': 18.15.5 dev: true - /@types/styled-components/5.1.26: + /@types/styled-components@5.1.26: resolution: {integrity: sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==} dependencies: '@types/hoist-non-react-statics': 3.3.1 @@ -3841,15 +4338,15 @@ packages: csstype: 3.1.1 dev: true - /@types/ua-parser-js/0.7.36: + /@types/ua-parser-js@0.7.36: resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==} dev: false - /@types/wrap-ansi/8.0.1: + /@types/wrap-ansi@8.0.1: resolution: {integrity: sha512-cjwgM6WWy9YakrQ36Pq0vg5XoNblVEaNq+/pHngKl4GyyDIxTeskPoG+tp4LsRk0lHrA4LaLJqlvYridi7mzlw==} dev: true - /@typescript-eslint/eslint-plugin/5.56.0_2hcjazgfnbtq42tcc73br2vup4: + /@typescript-eslint/eslint-plugin@5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3861,22 +4358,22 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.4.0 - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) '@typescript-eslint/scope-manager': 5.56.0 - '@typescript-eslint/type-utils': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu - '@typescript-eslint/utils': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/type-utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) + '@typescript-eslint/utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) debug: 4.3.4 eslint: 8.36.0 grapheme-splitter: 1.0.4 ignore: 5.2.0 natural-compare-lite: 1.4.0 semver: 7.3.8 - tsutils: 3.21.0_typescript@5.0.2 + tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/parser/5.56.0_j4766f7ecgqbon3u7zlxn5zszu: + /@typescript-eslint/parser@5.56.0(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3888,21 +4385,21 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/types': 5.56.0 - '@typescript-eslint/typescript-estree': 5.56.0_typescript@5.0.2 + '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) debug: 4.3.4 eslint: 8.36.0 typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/scope-manager/5.56.0: + /@typescript-eslint/scope-manager@5.56.0: resolution: {integrity: sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.56.0 '@typescript-eslint/visitor-keys': 5.56.0 - /@typescript-eslint/type-utils/5.56.0_j4766f7ecgqbon3u7zlxn5zszu: + /@typescript-eslint/type-utils@5.56.0(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3912,20 +4409,20 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.56.0_typescript@5.0.2 - '@typescript-eslint/utils': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) + '@typescript-eslint/utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) debug: 4.3.4 eslint: 8.36.0 - tsutils: 3.21.0_typescript@5.0.2 + tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/types/5.56.0: + /@typescript-eslint/types@5.56.0: resolution: {integrity: sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@typescript-eslint/typescript-estree/5.56.0_typescript@5.0.2: + /@typescript-eslint/typescript-estree@5.56.0(typescript@5.0.2): resolution: {integrity: sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3940,23 +4437,23 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.8 - tsutils: 3.21.0_typescript@5.0.2 + tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: - supports-color - /@typescript-eslint/utils/5.56.0_j4766f7ecgqbon3u7zlxn5zszu: + /@typescript-eslint/utils@5.56.0(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.3.0_eslint@8.36.0 + '@eslint-community/eslint-utils': 4.3.0(eslint@8.36.0) '@types/json-schema': 7.0.11 '@types/semver': 7.3.13 '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/types': 5.56.0 - '@typescript-eslint/typescript-estree': 5.56.0_typescript@5.0.2 + '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) eslint: 8.36.0 eslint-scope: 5.1.1 semver: 7.3.8 @@ -3964,33 +4461,55 @@ packages: - supports-color - typescript - /@typescript-eslint/visitor-keys/5.56.0: + /@typescript-eslint/visitor-keys@5.56.0: resolution: {integrity: sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.56.0 eslint-visitor-keys: 3.3.0 - /@vitest/expect/0.29.7: + /@vitest/expect@0.29.7: resolution: {integrity: sha512-UtG0tW0DP6b3N8aw7PHmweKDsvPv4wjGvrVZW7OSxaFg76ShtVdMiMcUkZJgCE8QWUmhwaM0aQhbbVLo4F4pkA==} dependencies: '@vitest/spy': 0.29.7 '@vitest/utils': 0.29.7 chai: 4.3.7 - /@vitest/runner/0.29.7: + /@vitest/expect@0.29.8: + resolution: {integrity: sha512-xlcVXn5I5oTq6NiZSY3ykyWixBxr5mG8HYtjvpgg6KaqHm0mvhX18xuwl5YGxIRNt/A5jidd7CWcNHrSvgaQqQ==} + dependencies: + '@vitest/spy': 0.29.8 + '@vitest/utils': 0.29.8 + chai: 4.3.7 + dev: true + + /@vitest/runner@0.29.7: resolution: {integrity: sha512-Yt0+csM945+odOx4rjZSjibQfl2ymxqVsmYz6sO2fiO5RGPYDFCo60JF6tLL9pz4G/kjY4irUxadeB1XT+H1jg==} dependencies: '@vitest/utils': 0.29.7 p-limit: 4.0.0 pathe: 1.1.0 - /@vitest/spy/0.29.7: + /@vitest/runner@0.29.8: + resolution: {integrity: sha512-FzdhnRDwEr/A3Oo1jtIk/B952BBvP32n1ObMEb23oEJNO+qO5cBet6M2XWIDQmA7BDKGKvmhUf2naXyp/2JEwQ==} + dependencies: + '@vitest/utils': 0.29.8 + p-limit: 4.0.0 + pathe: 1.1.0 + dev: true + + /@vitest/spy@0.29.7: resolution: {integrity: sha512-IalL0iO6A6Xz8hthR8sctk6ZS//zVBX48EiNwQguYACdgdei9ZhwMaBFV70mpmeYAFCRAm+DpoFHM5470Im78A==} dependencies: tinyspy: 1.0.2 - /@vitest/ui/0.29.7: + /@vitest/spy@0.29.8: + resolution: {integrity: sha512-VdjBe9w34vOMl5I5mYEzNX8inTxrZ+tYUVk9jxaZJmHFwmDFC/GV3KBFTA/JKswr3XHvZL+FE/yq5EVhb6pSAw==} + dependencies: + tinyspy: 1.0.2 + dev: true + + /@vitest/ui@0.29.7: resolution: {integrity: sha512-KeOztcAldlFU5i8DKCQcmGrih1dVowurZy/9iPz5JyQdPJzej+nW1nI4nYvc4ZmUtA8+IAe9uViqnU7IXc1RNw==} dependencies: fast-glob: 3.2.12 @@ -4000,7 +4519,17 @@ packages: sirv: 2.0.2 dev: true - /@vitest/utils/0.29.7: + /@vitest/ui@0.29.8: + resolution: {integrity: sha512-+vbLd+c1R/XUWfzJsWeyjeiw13fwJ95I5tguxaqXRg61y9iYUKesVljg7Pttp2uo7VK+kAjvY91J41NZ1Vx3vg==} + dependencies: + fast-glob: 3.2.12 + flatted: 3.2.7 + pathe: 1.1.0 + picocolors: 1.0.0 + sirv: 2.0.2 + dev: true + + /@vitest/utils@0.29.7: resolution: {integrity: sha512-vNgGadp2eE5XKCXtZXL5UyNEDn68npSct75OC9AlELenSK0DiV1Mb9tfkwJHKjRb69iek+e79iipoJx8+s3SdA==} dependencies: cli-truncate: 3.1.0 @@ -4008,7 +4537,16 @@ packages: loupe: 2.3.6 pretty-format: 27.5.1 - /@vue/compiler-core/3.2.41: + /@vitest/utils@0.29.8: + resolution: {integrity: sha512-qGzuf3vrTbnoY+RjjVVIBYfuWMjn3UMUqyQtdGNZ6ZIIyte7B37exj6LaVkrZiUTvzSadVvO/tJm8AEgbGCBPg==} + dependencies: + cli-truncate: 3.1.0 + diff: 5.1.0 + loupe: 2.3.6 + pretty-format: 27.5.1 + dev: true + + /@vue/compiler-core@3.2.41: resolution: {integrity: sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==} dependencies: '@babel/parser': 7.20.3 @@ -4017,14 +4555,14 @@ packages: source-map: 0.6.1 dev: false - /@vue/compiler-dom/3.2.41: + /@vue/compiler-dom@3.2.41: resolution: {integrity: sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==} dependencies: '@vue/compiler-core': 3.2.41 '@vue/shared': 3.2.41 dev: false - /@vue/compiler-sfc/3.2.41: + /@vue/compiler-sfc@3.2.41: resolution: {integrity: sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==} dependencies: '@babel/parser': 7.20.3 @@ -4039,14 +4577,14 @@ packages: source-map: 0.6.1 dev: false - /@vue/compiler-ssr/3.2.41: + /@vue/compiler-ssr@3.2.41: resolution: {integrity: sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==} dependencies: '@vue/compiler-dom': 3.2.41 '@vue/shared': 3.2.41 dev: false - /@vue/reactivity-transform/3.2.41: + /@vue/reactivity-transform@3.2.41: resolution: {integrity: sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==} dependencies: '@babel/parser': 7.20.3 @@ -4056,58 +4594,50 @@ packages: magic-string: 0.25.9 dev: false - /@vue/shared/3.2.41: + /@vue/shared@3.2.41: resolution: {integrity: sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==} dev: false - /@webcomponents/custom-elements/1.5.1: + /@webcomponents/custom-elements@1.5.1: resolution: {integrity: sha512-6T/XT3S1UHDlRWFSxRXdeSoYWczEl78sygNPS7jDyHVrfZcF/pUtWGYgxF4uviH59iPVw1eOWbhubm8CqO0MpA==} dev: true - /@wessberg/stringutil/1.0.19: + /@wessberg/stringutil@1.0.19: resolution: {integrity: sha512-9AZHVXWlpN8Cn9k5BC/O0Dzb9E9xfEMXzYrNunwvkUTvuK7xgQPVRZpLo+jWCOZ5r8oBa8NIrHuPEu1hzbb6bg==} engines: {node: '>=8.0.0'} dev: false - /abab/2.0.6: + /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - /acorn-globals/7.0.1: + /acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: acorn: 8.8.2 acorn-walk: 8.2.0 - /acorn-jsx/5.3.2_acorn@8.8.1: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.8.1 - dev: false - - /acorn-jsx/5.3.2_acorn@8.8.2: + /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.8.2 - /acorn-walk/8.2.0: + /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} - /acorn/8.8.1: + /acorn@8.8.1: resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} engines: {node: '>=0.4.0'} hasBin: true - /acorn/8.8.2: + /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} hasBin: true - /agent-base/6.0.2: + /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: @@ -4115,7 +4645,7 @@ packages: transitivePeerDependencies: - supports-color - /ajv/6.12.6: + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: fast-deep-equal: 3.1.3 @@ -4123,47 +4653,47 @@ packages: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - /ansi-colors/4.1.3: + /ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} - /ansi-regex/5.0.1: + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - /ansi-regex/6.0.1: + /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} - /ansi-styles/3.2.1: + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} dependencies: color-convert: 1.9.3 - /ansi-styles/4.3.0: + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - /ansi-styles/5.2.0: + /ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - /ansi-styles/6.2.1: + /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - /ansicolor/1.1.100: + /ansicolor@1.1.100: resolution: {integrity: sha512-Jl0pxRfa9WaQVUX57AB8/V2my6FJxrOR1Pp2qqFbig20QB4HzUoQ48THTKAgHlUCJeQm/s2WoOPcoIDhyCL/kw==} dev: false - /any-shell-escape/0.1.1: + /any-shell-escape@0.1.1: resolution: {integrity: sha512-36j4l5HVkboyRhIWgtMh1I9i8LTdFqVwDEHy1cp+QioJyKgAUG40X0W8s7jakWRta/Sjvm8mUG1fU6Tj8mWagQ==} dev: false - /anymatch/3.1.2: + /anymatch@3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} engines: {node: '>= 8'} dependencies: @@ -4171,25 +4701,25 @@ packages: picomatch: 2.3.1 dev: false - /argparse/1.0.10: + /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} dependencies: sprintf-js: 1.0.3 - /argparse/2.0.1: + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - /aria-query/5.1.3: + /aria-query@5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} dependencies: deep-equal: 2.2.0 - /array-differ/3.0.0: + /array-differ@3.0.0: resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} engines: {node: '>=8'} dev: false - /array-includes/3.1.6: + /array-includes@3.1.6: resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} engines: {node: '>= 0.4'} dependencies: @@ -4199,11 +4729,11 @@ packages: get-intrinsic: 1.2.0 is-string: 1.0.7 - /array-union/2.1.0: + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - /array.prototype.flat/1.3.1: + /array.prototype.flat@1.3.1: resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} engines: {node: '>= 0.4'} dependencies: @@ -4212,7 +4742,7 @@ packages: es-abstract: 1.20.4 es-shim-unscopables: 1.0.0 - /array.prototype.flatmap/1.3.1: + /array.prototype.flatmap@1.3.1: resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} engines: {node: '>= 0.4'} dependencies: @@ -4221,7 +4751,7 @@ packages: es-abstract: 1.20.4 es-shim-unscopables: 1.0.0 - /array.prototype.tosorted/1.1.1: + /array.prototype.tosorted@1.1.1: resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} dependencies: call-bind: 1.0.2 @@ -4231,42 +4761,42 @@ packages: get-intrinsic: 1.2.0 dev: true - /arrify/1.0.1: + /arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} dev: true - /arrify/2.0.1: + /arrify@2.0.1: resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} engines: {node: '>=8'} dev: false - /as-table/1.0.55: + /as-table@1.0.55: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} dependencies: printable-characters: 1.0.42 dev: false - /assertion-error/1.1.0: + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - /ast-types-flow/0.0.7: + /ast-types-flow@0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} dev: true - /asynckit/0.4.0: + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - /available-typed-arrays/1.0.5: + /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} - /axe-core/4.6.3: + /axe-core@4.6.3: resolution: {integrity: sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==} engines: {node: '>=4'} dev: true - /axios/1.2.2: + /axios@1.2.2: resolution: {integrity: sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==} dependencies: follow-redirects: 1.15.2 @@ -4275,49 +4805,49 @@ packages: transitivePeerDependencies: - debug - /axobject-query/3.1.1: + /axobject-query@3.1.1: resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} dependencies: deep-equal: 2.2.0 dev: true - /babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.21.3: + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.21.3): resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/compat-data': 7.20.1 '@babel/core': 7.21.3 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-corejs3/0.6.0_@babel+core@7.21.3: + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.21.3): resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) core-js-compat: 3.26.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-regenerator/0.4.1_@babel+core@7.21.3: + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.21.3): resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.21.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) transitivePeerDependencies: - supports-color dev: true - /babel-plugin-styled-components/2.0.7_styled-components@5.3.6: + /babel-plugin-styled-components@2.0.7(styled-components@5.3.6): resolution: {integrity: sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==} peerDependencies: styled-components: '>= 2' @@ -4327,60 +4857,60 @@ packages: babel-plugin-syntax-jsx: 6.18.0 lodash: 4.17.21 picomatch: 2.3.1 - styled-components: 5.3.6_pumtretovylab5lwhztzjp2kuy + styled-components: 5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) dev: true - /babel-plugin-syntax-jsx/6.18.0: + /babel-plugin-syntax-jsx@6.18.0: resolution: {integrity: sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==} dev: true - /balanced-match/1.0.2: + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - /base64-js/1.5.1: + /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: false - /better-path-resolve/1.0.0: + /better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} dependencies: is-windows: 1.0.2 dev: true - /binary-extensions/2.2.0: + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: false - /boolbase/1.0.0: + /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - /brace-expansion/1.1.11: + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - /brace-expansion/2.0.1: + /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 dev: false - /braces/3.0.2: + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - /breakword/1.0.5: + /breakword@1.0.5: resolution: {integrity: sha512-ex5W9DoOQ/LUEU3PMdLs9ua/CYZl1678NUkKOdUSi8Aw5F1idieaiRURCBFJCwVcrD1J8Iy3vfWSloaMwO2qFg==} dependencies: wcwidth: 1.0.1 dev: true - /browserslist-generator/1.0.66: + /browserslist-generator@1.0.66: resolution: {integrity: sha512-aFDax4Qzh29DdyhHQBD2Yu2L5OvaDnvYFMbmpLrLwwaNK4H6dHEhC/Nxv93/+mfAA+a/t94ln0P2JZvHO6LZDA==} engines: {node: '>=8.0.0'} dependencies: @@ -4396,7 +4926,7 @@ packages: ua-parser-js: 1.0.32 dev: false - /browserslist/4.20.2: + /browserslist@4.20.2: resolution: {integrity: sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -4408,7 +4938,7 @@ packages: picocolors: 1.0.0 dev: false - /browserslist/4.21.4: + /browserslist@4.21.4: resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -4416,39 +4946,39 @@ packages: caniuse-lite: 1.0.30001431 electron-to-chromium: 1.4.284 node-releases: 2.0.6 - update-browserslist-db: 1.0.10_browserslist@4.21.4 + update-browserslist-db: 1.0.10(browserslist@4.21.4) - /buffer-from/1.1.2: + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /buffer/6.0.3: + /buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} dependencies: base64-js: 1.5.1 ieee754: 1.2.1 dev: false - /builtin-modules/3.3.0: + /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} dev: false - /cac/6.7.14: + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - /call-bind/1.0.2: + /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 get-intrinsic: 1.2.0 - /callsites/3.1.0: + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - /camelcase-keys/6.2.2: + /camelcase-keys@6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} dependencies: @@ -4457,21 +4987,21 @@ packages: quick-lru: 4.0.1 dev: true - /camelcase/5.3.1: + /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} dev: true - /camelcase/6.3.0: + /camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} dev: false - /camelize/1.0.1: + /camelize@1.0.1: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: true - /caniuse-api/3.0.0: + /caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: browserslist: 4.21.4 @@ -4480,10 +5010,10 @@ packages: lodash.uniq: 4.5.0 dev: false - /caniuse-lite/1.0.30001431: + /caniuse-lite@1.0.30001431: resolution: {integrity: sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==} - /chai/4.3.7: + /chai@4.3.7: resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} engines: {node: '>=4'} dependencies: @@ -4495,7 +5025,7 @@ packages: pathval: 1.1.1 type-detect: 4.0.8 - /chalk/2.4.2: + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} dependencies: @@ -4503,25 +5033,25 @@ packages: escape-string-regexp: 1.0.5 supports-color: 5.5.0 - /chalk/4.1.2: + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - /chalk/5.2.0: + /chalk@5.2.0: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - /chardet/0.7.0: + /chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true - /check-error/1.0.2: + /check-error@1.0.2: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} - /cheerio-select/2.1.0: + /cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} dependencies: boolbase: 1.0.0 @@ -4532,7 +5062,7 @@ packages: domutils: 3.0.1 dev: true - /cheerio/1.0.0-rc.12: + /cheerio@1.0.0-rc.12: resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} engines: {node: '>= 6'} dependencies: @@ -4545,11 +5075,11 @@ packages: parse5-htmlparser2-tree-adapter: 7.0.0 dev: true - /child_process/1.0.2: + /child_process@1.0.2: resolution: {integrity: sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==} dev: false - /chokidar/3.5.3: + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} dependencies: @@ -4564,15 +5094,15 @@ packages: fsevents: 2.3.2 dev: false - /chrome-types/0.1.159: + /chrome-types@0.1.159: resolution: {integrity: sha512-A267cwetV1ninoID9ox6DPfqKbThHMV28sR1jy/Dog0MxxIQpkJqtUqcpQS+D/8pCDOtAB17pfywstKkaeuMEw==} dev: true - /ci-info/3.5.0: + /ci-info@3.5.0: resolution: {integrity: sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==} dev: true - /cli-table3/0.6.3: + /cli-table3@0.6.3: resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} engines: {node: 10.* || >= 12.*} dependencies: @@ -4580,14 +5110,14 @@ packages: optionalDependencies: '@colors/colors': 1.5.0 - /cli-truncate/3.1.0: + /cli-truncate@3.1.0: resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: slice-ansi: 5.0.0 string-width: 5.1.2 - /cliui/6.0.0: + /cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: string-width: 4.2.3 @@ -4595,14 +5125,14 @@ packages: wrap-ansi: 6.2.0 dev: true - /cliui/7.0.4: + /cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - /cliui/8.0.1: + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} dependencies: @@ -4611,53 +5141,53 @@ packages: wrap-ansi: 7.0.0 dev: true - /clone/1.0.4: + /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} dev: true - /color-convert/1.9.3: + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: color-name: 1.1.3 - /color-convert/2.0.1: + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - /color-name/1.1.3: + /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - /color-name/1.1.4: + /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - /colord/2.9.3: + /colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} dev: false - /combined-stream/1.0.8: + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - /commander/7.2.0: + /commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} dev: false - /commander/9.4.1: + /commander@9.4.1: resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} engines: {node: ^12.20.0 || >=14} dev: false - /commondir/1.0.1: + /commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} dev: false - /compatfactory/1.0.1_typescript@5.0.2: + /compatfactory@1.0.1(typescript@5.0.2): resolution: {integrity: sha512-hR9u0HSZTKDNNchPtMHg6myeNx0XO+av7UZIJPsi4rPALJBHi/W5Mbwi19hC/xm6y3JkYpxVYjTqnSGsU5X/iw==} engines: {node: '>=14.9.0'} peerDependencies: @@ -4667,25 +5197,25 @@ packages: typescript: 5.0.2 dev: false - /concat-map/0.0.1: + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - /concat-with-sourcemaps/1.1.0: + /concat-with-sourcemaps@1.1.0: resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} dependencies: source-map: 0.6.1 dev: false - /confusing-browser-globals/1.0.11: + /confusing-browser-globals@1.0.11: resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} dev: true - /connect-history-api-fallback/1.6.0: + /connect-history-api-fallback@1.6.0: resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} engines: {node: '>=0.8'} dev: true - /connect-injector/0.4.4: + /connect-injector@0.4.4: resolution: {integrity: sha512-hdBG8nXop42y2gWCqOV8y1O3uVk4cIU+SoxLCPyCUKRImyPiScoNiSulpHjoktRU1BdI0UzoUdxUa87thrcmHw==} engines: {node: '>= 0.8.0'} dependencies: @@ -4697,17 +5227,17 @@ packages: - supports-color dev: true - /convert-source-map/1.9.0: + /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true - /core-js-compat/3.26.0: + /core-js-compat@3.26.0: resolution: {integrity: sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==} dependencies: browserslist: 4.21.4 dev: true - /cosmiconfig/7.0.1: + /cosmiconfig@7.0.1: resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} engines: {node: '>=10'} dependencies: @@ -4718,7 +5248,7 @@ packages: yaml: 1.10.2 dev: false - /cross-spawn/5.1.0: + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: lru-cache: 4.1.5 @@ -4726,7 +5256,7 @@ packages: which: 1.3.1 dev: true - /cross-spawn/7.0.3: + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} dependencies: @@ -4734,19 +5264,19 @@ packages: shebang-command: 2.0.0 which: 2.0.2 - /crosspath/2.0.0: + /crosspath@2.0.0: resolution: {integrity: sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA==} engines: {node: '>=14.9.0'} dependencies: '@types/node': 18.15.5 dev: false - /css-color-keywords/1.0.0: + /css-color-keywords@1.0.0: resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} engines: {node: '>=4'} dev: true - /css-declaration-sorter/6.3.1_postcss@8.4.20: + /css-declaration-sorter@6.3.1(postcss@8.4.20): resolution: {integrity: sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==} engines: {node: ^10 || ^12 || >=14} peerDependencies: @@ -4755,7 +5285,7 @@ packages: postcss: 8.4.20 dev: false - /css-select/4.3.0: + /css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} dependencies: boolbase: 1.0.0 @@ -4765,7 +5295,7 @@ packages: nth-check: 2.1.1 dev: false - /css-select/5.1.0: + /css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} dependencies: boolbase: 1.0.0 @@ -4775,7 +5305,7 @@ packages: nth-check: 2.1.1 dev: true - /css-to-react-native/3.0.0: + /css-to-react-native@3.0.0: resolution: {integrity: sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==} dependencies: camelize: 1.0.1 @@ -4783,7 +5313,7 @@ packages: postcss-value-parser: 4.2.0 dev: true - /css-tree/1.1.3: + /css-tree@1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} dependencies: @@ -4791,59 +5321,59 @@ packages: source-map: 0.6.1 dev: false - /css-what/6.1.0: + /css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - /css.escape/1.5.1: + /css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} dev: true - /cssesc/3.0.0: + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true dev: false - /cssnano-preset-default/5.2.13_postcss@8.4.20: + /cssnano-preset-default@5.2.13(postcss@8.4.20): resolution: {integrity: sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: - css-declaration-sorter: 6.3.1_postcss@8.4.20 - cssnano-utils: 3.1.0_postcss@8.4.20 + css-declaration-sorter: 6.3.1(postcss@8.4.20) + cssnano-utils: 3.1.0(postcss@8.4.20) postcss: 8.4.20 - postcss-calc: 8.2.4_postcss@8.4.20 - postcss-colormin: 5.3.0_postcss@8.4.20 - postcss-convert-values: 5.1.3_postcss@8.4.20 - postcss-discard-comments: 5.1.2_postcss@8.4.20 - postcss-discard-duplicates: 5.1.0_postcss@8.4.20 - postcss-discard-empty: 5.1.1_postcss@8.4.20 - postcss-discard-overridden: 5.1.0_postcss@8.4.20 - postcss-merge-longhand: 5.1.7_postcss@8.4.20 - postcss-merge-rules: 5.1.3_postcss@8.4.20 - postcss-minify-font-values: 5.1.0_postcss@8.4.20 - postcss-minify-gradients: 5.1.1_postcss@8.4.20 - postcss-minify-params: 5.1.4_postcss@8.4.20 - postcss-minify-selectors: 5.2.1_postcss@8.4.20 - postcss-normalize-charset: 5.1.0_postcss@8.4.20 - postcss-normalize-display-values: 5.1.0_postcss@8.4.20 - postcss-normalize-positions: 5.1.1_postcss@8.4.20 - postcss-normalize-repeat-style: 5.1.1_postcss@8.4.20 - postcss-normalize-string: 5.1.0_postcss@8.4.20 - postcss-normalize-timing-functions: 5.1.0_postcss@8.4.20 - postcss-normalize-unicode: 5.1.1_postcss@8.4.20 - postcss-normalize-url: 5.1.0_postcss@8.4.20 - postcss-normalize-whitespace: 5.1.1_postcss@8.4.20 - postcss-ordered-values: 5.1.3_postcss@8.4.20 - postcss-reduce-initial: 5.1.1_postcss@8.4.20 - postcss-reduce-transforms: 5.1.0_postcss@8.4.20 - postcss-svgo: 5.1.0_postcss@8.4.20 - postcss-unique-selectors: 5.1.1_postcss@8.4.20 - dev: false - - /cssnano-utils/3.1.0_postcss@8.4.20: + postcss-calc: 8.2.4(postcss@8.4.20) + postcss-colormin: 5.3.0(postcss@8.4.20) + postcss-convert-values: 5.1.3(postcss@8.4.20) + postcss-discard-comments: 5.1.2(postcss@8.4.20) + postcss-discard-duplicates: 5.1.0(postcss@8.4.20) + postcss-discard-empty: 5.1.1(postcss@8.4.20) + postcss-discard-overridden: 5.1.0(postcss@8.4.20) + postcss-merge-longhand: 5.1.7(postcss@8.4.20) + postcss-merge-rules: 5.1.3(postcss@8.4.20) + postcss-minify-font-values: 5.1.0(postcss@8.4.20) + postcss-minify-gradients: 5.1.1(postcss@8.4.20) + postcss-minify-params: 5.1.4(postcss@8.4.20) + postcss-minify-selectors: 5.2.1(postcss@8.4.20) + postcss-normalize-charset: 5.1.0(postcss@8.4.20) + postcss-normalize-display-values: 5.1.0(postcss@8.4.20) + postcss-normalize-positions: 5.1.1(postcss@8.4.20) + postcss-normalize-repeat-style: 5.1.1(postcss@8.4.20) + postcss-normalize-string: 5.1.0(postcss@8.4.20) + postcss-normalize-timing-functions: 5.1.0(postcss@8.4.20) + postcss-normalize-unicode: 5.1.1(postcss@8.4.20) + postcss-normalize-url: 5.1.0(postcss@8.4.20) + postcss-normalize-whitespace: 5.1.1(postcss@8.4.20) + postcss-ordered-values: 5.1.3(postcss@8.4.20) + postcss-reduce-initial: 5.1.1(postcss@8.4.20) + postcss-reduce-transforms: 5.1.0(postcss@8.4.20) + postcss-svgo: 5.1.0(postcss@8.4.20) + postcss-unique-selectors: 5.1.1(postcss@8.4.20) + dev: false + + /cssnano-utils@3.1.0(postcss@8.4.20): resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -4852,60 +5382,60 @@ packages: postcss: 8.4.20 dev: false - /cssnano/5.1.14_postcss@8.4.20: + /cssnano@5.1.14(postcss@8.4.20): resolution: {integrity: sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: - cssnano-preset-default: 5.2.13_postcss@8.4.20 + cssnano-preset-default: 5.2.13(postcss@8.4.20) lilconfig: 2.0.6 postcss: 8.4.20 yaml: 1.10.2 dev: false - /csso/4.2.0: + /csso@4.2.0: resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} engines: {node: '>=8.0.0'} dependencies: css-tree: 1.1.3 dev: false - /cssom/0.3.8: + /cssom@0.3.8: resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - /cssom/0.5.0: + /cssom@0.5.0: resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - /cssstyle/2.3.0: + /cssstyle@2.3.0: resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} engines: {node: '>=8'} dependencies: cssom: 0.3.8 - /cssstyle/3.0.0: + /cssstyle@3.0.0: resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} engines: {node: '>=14'} dependencies: rrweb-cssom: 0.6.0 - /csstype/3.1.1: + /csstype@3.1.1: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: true - /csv-generate/3.4.3: + /csv-generate@3.4.3: resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} dev: true - /csv-parse/4.16.3: + /csv-parse@4.16.3: resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} dev: true - /csv-stringify/5.6.5: + /csv-stringify@5.6.5: resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} dev: true - /csv/5.5.3: + /csv@5.5.3: resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} engines: {node: '>= 0.1.90'} dependencies: @@ -4915,15 +5445,15 @@ packages: stream-transform: 2.1.3 dev: true - /damerau-levenshtein/1.0.8: + /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true - /data-uri-to-buffer/2.0.2: + /data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} dev: false - /data-urls/3.0.2: + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} dependencies: @@ -4931,7 +5461,7 @@ packages: whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - /data-urls/4.0.0: + /data-urls@4.0.0: resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} engines: {node: '>=14'} dependencies: @@ -4939,7 +5469,7 @@ packages: whatwg-mimetype: 3.0.0 whatwg-url: 12.0.1 - /debug/2.6.9: + /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: supports-color: '*' @@ -4950,7 +5480,7 @@ packages: ms: 2.0.0 dev: true - /debug/3.2.7: + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' @@ -4960,7 +5490,7 @@ packages: dependencies: ms: 2.1.3 - /debug/4.3.4: + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -4971,7 +5501,7 @@ packages: dependencies: ms: 2.1.2 - /debug/4.3.4_supports-color@5.5.0: + /debug@4.3.4(supports-color@5.5.0): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -4984,7 +5514,7 @@ packages: supports-color: 5.5.0 dev: true - /decamelize-keys/1.1.1: + /decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} dependencies: @@ -4992,24 +5522,24 @@ packages: map-obj: 1.0.1 dev: true - /decamelize/1.2.0: + /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} dev: true - /decimal.js/10.4.2: + /decimal.js@10.4.2: resolution: {integrity: sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==} - /decimal.js/10.4.3: + /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - /deep-eql/4.1.2: + /deep-eql@4.1.2: resolution: {integrity: sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==} engines: {node: '>=6'} dependencies: type-detect: 4.0.8 - /deep-equal/2.2.0: + /deep-equal@2.2.0: resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} dependencies: call-bind: 1.0.2 @@ -5030,36 +5560,36 @@ packages: which-collection: 1.0.1 which-typed-array: 1.1.9 - /deep-is/0.1.4: + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - /deepmerge/4.2.2: + /deepmerge@4.2.2: resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} engines: {node: '>=0.10.0'} dev: false - /defaults/1.0.4: + /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: clone: 1.0.4 dev: true - /define-lazy-prop/2.0.0: + /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} - /define-properties/1.2.0: + /define-properties@1.2.0: resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} engines: {node: '>= 0.4'} dependencies: has-property-descriptors: 1.0.0 object-keys: 1.1.1 - /delayed-stream/1.0.0: + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - /depcheck/1.4.3: + /depcheck@1.4.3: resolution: {integrity: sha512-vy8xe1tlLFu7t4jFyoirMmOR7x7N601ubU9Gkifyr9z8rjBFtEdWHDBMqXyk6OkK+94NXutzddVXJuo0JlUQKQ==} engines: {node: '>=10'} hasBin: true @@ -5091,52 +5621,52 @@ packages: - supports-color dev: false - /deps-regex/0.1.4: + /deps-regex@0.1.4: resolution: {integrity: sha512-3tzwGYogSJi8HoG93R5x9NrdefZQOXgHgGih/7eivloOq6yC6O+yoFxZnkgP661twvfILONfoKRdF9GQOGx2RA==} dev: false - /detect-indent/6.1.0: + /detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} dev: true - /diff/5.1.0: + /diff@5.1.0: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} engines: {node: '>=0.3.1'} - /dir-glob/3.0.1: + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} dependencies: path-type: 4.0.0 - /dirfilename/1.1.1: + /dirfilename@1.1.1: resolution: {integrity: sha512-ovfE0+nTK5JhKW4XXcR+M1CjHFtL6Mor4yzlpb1sJcSA2KlMIZLWSKP5NHz+2GF9oqoJlQEZEhJa2KsocfpvDQ==} engines: {node: '>=16.0.0'} - /doctrine/2.1.0: + /doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} dependencies: esutils: 2.0.3 - /doctrine/3.0.0: + /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} dependencies: esutils: 2.0.3 - /dom-accessibility-api/0.5.14: + /dom-accessibility-api@0.5.14: resolution: {integrity: sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==} - /dom-helpers/5.2.1: + /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: '@babel/runtime': 7.21.0 csstype: 3.1.1 dev: true - /dom-serializer/1.4.1: + /dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} dependencies: domelementtype: 2.3.0 @@ -5144,7 +5674,7 @@ packages: entities: 2.2.0 dev: false - /dom-serializer/2.0.0: + /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: domelementtype: 2.3.0 @@ -5152,30 +5682,30 @@ packages: entities: 4.4.0 dev: true - /domelementtype/2.3.0: + /domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - /domexception/4.0.0: + /domexception@4.0.0: resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} engines: {node: '>=12'} dependencies: webidl-conversions: 7.0.0 - /domhandler/4.3.1: + /domhandler@4.3.1: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} dependencies: domelementtype: 2.3.0 dev: false - /domhandler/5.0.3: + /domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} dependencies: domelementtype: 2.3.0 dev: true - /domutils/2.8.0: + /domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} dependencies: dom-serializer: 1.4.1 @@ -5183,7 +5713,7 @@ packages: domhandler: 4.3.1 dev: false - /domutils/3.0.1: + /domutils@3.0.1: resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} dependencies: dom-serializer: 2.0.0 @@ -5191,50 +5721,50 @@ packages: domhandler: 5.0.3 dev: true - /eastasianwidth/0.2.0: + /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - /electron-to-chromium/1.4.284: + /electron-to-chromium@1.4.284: resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} - /emoji-regex/10.2.1: + /emoji-regex@10.2.1: resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==} dev: false - /emoji-regex/8.0.0: + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - /emoji-regex/9.2.2: + /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - /enhanced-resolve/5.10.0: + /enhanced-resolve@5.10.0: resolution: {integrity: sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==} engines: {node: '>=10.13.0'} dependencies: graceful-fs: 4.2.10 tapable: 2.2.1 - /enquirer/2.3.6: + /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} dependencies: ansi-colors: 4.1.3 dev: true - /entities/2.2.0: + /entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: false - /entities/4.4.0: + /entities@4.4.0: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} - /error-ex/1.3.2: + /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 - /es-abstract/1.20.4: + /es-abstract@1.20.4: resolution: {integrity: sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==} engines: {node: '>= 0.4'} dependencies: @@ -5263,7 +5793,7 @@ packages: string.prototype.trimstart: 1.0.6 unbox-primitive: 1.0.2 - /es-get-iterator/1.1.3: + /es-get-iterator@1.1.3: resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} dependencies: call-bind: 1.0.2 @@ -5276,16 +5806,16 @@ packages: isarray: 2.0.5 stop-iteration-iterator: 1.0.0 - /es-module-lexer/0.10.5: + /es-module-lexer@0.10.5: resolution: {integrity: sha512-+7IwY/kiGAacQfY+YBhKMvEmyAJnw5grTUgjG85Pe7vcUI/6b7pZjZG8nQ7+48YhzEAEqrEgD2dCz/JIK+AYvw==} dev: true - /es-shim-unscopables/1.0.0: + /es-shim-unscopables@1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} dependencies: has: 1.0.3 - /es-to-primitive/1.2.1: + /es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: @@ -5293,7 +5823,7 @@ packages: is-date-object: 1.0.5 is-symbol: 1.0.4 - /esbuild-android-64/0.15.13: + /esbuild-android-64@0.15.13: resolution: {integrity: sha512-yRorukXBlokwTip+Sy4MYskLhJsO0Kn0/Fj43s1krVblfwP+hMD37a4Wmg139GEsMLl+vh8WXp2mq/cTA9J97g==} engines: {node: '>=12'} cpu: [x64] @@ -5302,7 +5832,7 @@ packages: dev: true optional: true - /esbuild-android-arm64/0.15.13: + /esbuild-android-arm64@0.15.13: resolution: {integrity: sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==} engines: {node: '>=12'} cpu: [arm64] @@ -5311,7 +5841,7 @@ packages: dev: true optional: true - /esbuild-darwin-64/0.15.13: + /esbuild-darwin-64@0.15.13: resolution: {integrity: sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==} engines: {node: '>=12'} cpu: [x64] @@ -5320,7 +5850,7 @@ packages: dev: true optional: true - /esbuild-darwin-arm64/0.15.13: + /esbuild-darwin-arm64@0.15.13: resolution: {integrity: sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==} engines: {node: '>=12'} cpu: [arm64] @@ -5329,7 +5859,7 @@ packages: dev: true optional: true - /esbuild-freebsd-64/0.15.13: + /esbuild-freebsd-64@0.15.13: resolution: {integrity: sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==} engines: {node: '>=12'} cpu: [x64] @@ -5338,7 +5868,7 @@ packages: dev: true optional: true - /esbuild-freebsd-arm64/0.15.13: + /esbuild-freebsd-arm64@0.15.13: resolution: {integrity: sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==} engines: {node: '>=12'} cpu: [arm64] @@ -5347,7 +5877,7 @@ packages: dev: true optional: true - /esbuild-linux-32/0.15.13: + /esbuild-linux-32@0.15.13: resolution: {integrity: sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==} engines: {node: '>=12'} cpu: [ia32] @@ -5356,7 +5886,7 @@ packages: dev: true optional: true - /esbuild-linux-64/0.15.13: + /esbuild-linux-64@0.15.13: resolution: {integrity: sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==} engines: {node: '>=12'} cpu: [x64] @@ -5365,25 +5895,25 @@ packages: dev: true optional: true - /esbuild-linux-arm/0.15.13: - resolution: {integrity: sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==} + /esbuild-linux-arm64@0.15.13: + resolution: {integrity: sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==} engines: {node: '>=12'} - cpu: [arm] + cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-arm64/0.15.13: - resolution: {integrity: sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==} + /esbuild-linux-arm@0.15.13: + resolution: {integrity: sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-mips64le/0.15.13: + /esbuild-linux-mips64le@0.15.13: resolution: {integrity: sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==} engines: {node: '>=12'} cpu: [mips64el] @@ -5392,7 +5922,7 @@ packages: dev: true optional: true - /esbuild-linux-ppc64le/0.15.13: + /esbuild-linux-ppc64le@0.15.13: resolution: {integrity: sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==} engines: {node: '>=12'} cpu: [ppc64] @@ -5401,7 +5931,7 @@ packages: dev: true optional: true - /esbuild-linux-riscv64/0.15.13: + /esbuild-linux-riscv64@0.15.13: resolution: {integrity: sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==} engines: {node: '>=12'} cpu: [riscv64] @@ -5410,7 +5940,7 @@ packages: dev: true optional: true - /esbuild-linux-s390x/0.15.13: + /esbuild-linux-s390x@0.15.13: resolution: {integrity: sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==} engines: {node: '>=12'} cpu: [s390x] @@ -5419,7 +5949,7 @@ packages: dev: true optional: true - /esbuild-netbsd-64/0.15.13: + /esbuild-netbsd-64@0.15.13: resolution: {integrity: sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==} engines: {node: '>=12'} cpu: [x64] @@ -5428,7 +5958,7 @@ packages: dev: true optional: true - /esbuild-openbsd-64/0.15.13: + /esbuild-openbsd-64@0.15.13: resolution: {integrity: sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==} engines: {node: '>=12'} cpu: [x64] @@ -5437,7 +5967,7 @@ packages: dev: true optional: true - /esbuild-sunos-64/0.15.13: + /esbuild-sunos-64@0.15.13: resolution: {integrity: sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==} engines: {node: '>=12'} cpu: [x64] @@ -5446,7 +5976,7 @@ packages: dev: true optional: true - /esbuild-windows-32/0.15.13: + /esbuild-windows-32@0.15.13: resolution: {integrity: sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==} engines: {node: '>=12'} cpu: [ia32] @@ -5455,7 +5985,7 @@ packages: dev: true optional: true - /esbuild-windows-64/0.15.13: + /esbuild-windows-64@0.15.13: resolution: {integrity: sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==} engines: {node: '>=12'} cpu: [x64] @@ -5464,7 +5994,7 @@ packages: dev: true optional: true - /esbuild-windows-arm64/0.15.13: + /esbuild-windows-arm64@0.15.13: resolution: {integrity: sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==} engines: {node: '>=12'} cpu: [arm64] @@ -5473,7 +6003,7 @@ packages: dev: true optional: true - /esbuild/0.15.13: + /esbuild@0.15.13: resolution: {integrity: sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==} engines: {node: '>=12'} hasBin: true @@ -5503,7 +6033,7 @@ packages: esbuild-windows-arm64: 0.15.13 dev: true - /esbuild/0.17.12: + /esbuild@0.17.12: resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==} engines: {node: '>=12'} hasBin: true @@ -5532,19 +6062,19 @@ packages: '@esbuild/win32-ia32': 0.17.12 '@esbuild/win32-x64': 0.17.12 - /escalade/3.1.1: + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} - /escape-string-regexp/1.0.5: + /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - /escape-string-regexp/4.0.0: + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - /escodegen/2.0.0: + /escodegen@2.0.0: resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} engines: {node: '>=6.0'} hasBin: true @@ -5556,7 +6086,7 @@ packages: optionalDependencies: source-map: 0.6.1 - /eslint-config-airbnb-base/15.0.0_eakrjjutlgqjxe5ydhtnd4qdmy: + /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.27.5)(eslint@8.36.0): resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -5565,13 +6095,13 @@ packages: dependencies: confusing-browser-globals: 1.0.11 eslint: 8.36.0 - eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) object.assign: 4.1.4 object.entries: 1.1.6 semver: 6.3.0 dev: true - /eslint-config-airbnb/19.0.4_guhfqc3yvckhutqwrddiy54d5i: + /eslint-config-airbnb@19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.36.0): resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -5582,16 +6112,16 @@ packages: eslint-plugin-react-hooks: ^4.3.0 dependencies: eslint: 8.36.0 - eslint-config-airbnb-base: 15.0.0_eakrjjutlgqjxe5ydhtnd4qdmy - eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq - eslint-plugin-jsx-a11y: 6.7.1_eslint@8.36.0 - eslint-plugin-react: 7.32.2_eslint@8.36.0 - eslint-plugin-react-hooks: 4.6.0_eslint@8.36.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.36.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint-plugin-jsx-a11y: 6.7.1(eslint@8.36.0) + eslint-plugin-react: 7.32.2(eslint@8.36.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.36.0) object.assign: 4.1.4 object.entries: 1.1.6 dev: true - /eslint-config-prettier/8.8.0_eslint@8.36.0: + /eslint-config-prettier@8.8.0(eslint@8.36.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true peerDependencies: @@ -5599,7 +6129,7 @@ packages: dependencies: eslint: 8.36.0 - /eslint-import-resolver-node/0.3.7: + /eslint-import-resolver-node@0.3.7: resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} dependencies: debug: 3.2.7 @@ -5608,7 +6138,7 @@ packages: transitivePeerDependencies: - supports-color - /eslint-import-resolver-typescript/3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy: + /eslint-import-resolver-typescript@3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0): resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -5618,7 +6148,7 @@ packages: debug: 4.3.4 enhanced-resolve: 5.10.0 eslint: 8.36.0 - eslint-plugin-import: 2.27.5_as6wyplljmmarlclp2tx3tj6rq + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) get-tsconfig: 4.2.0 globby: 13.1.2 is-core-module: 2.11.0 @@ -5627,7 +6157,7 @@ packages: transitivePeerDependencies: - supports-color - /eslint-module-utils/2.7.4_ab4tb467oik4rhsaavmctlutka: + /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -5648,15 +6178,15 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) debug: 3.2.7 eslint: 8.36.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.3_eakrjjutlgqjxe5ydhtnd4qdmy + eslint-import-resolver-typescript: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0) transitivePeerDependencies: - supports-color - /eslint-module-utils/2.7.4_tf7h2azriypc3gaglz256o6pea: + /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint@8.36.0): resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -5677,7 +6207,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) debug: 3.2.7 eslint: 8.36.0 eslint-import-resolver-node: 0.3.7 @@ -5685,7 +6215,7 @@ packages: - supports-color dev: false - /eslint-plugin-import/2.27.5_as6wyplljmmarlclp2tx3tj6rq: + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -5695,7 +6225,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -5703,7 +6233,7 @@ packages: doctrine: 2.1.0 eslint: 8.36.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_ab4tb467oik4rhsaavmctlutka + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -5717,7 +6247,7 @@ packages: - eslint-import-resolver-webpack - supports-color - /eslint-plugin-import/2.27.5_cnkxirszkzb4o6ts7gbclno24e: + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint@8.36.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -5727,7 +6257,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.56.0_j4766f7ecgqbon3u7zlxn5zszu + '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -5735,7 +6265,7 @@ packages: doctrine: 2.1.0 eslint: 8.36.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_tf7h2azriypc3gaglz256o6pea + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint@8.36.0) has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -5750,7 +6280,7 @@ packages: - supports-color dev: false - /eslint-plugin-json/3.1.0: + /eslint-plugin-json@3.1.0: resolution: {integrity: sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==} engines: {node: '>=12.0'} dependencies: @@ -5758,18 +6288,18 @@ packages: vscode-json-languageservice: 4.2.1 dev: false - /eslint-plugin-jsonc/2.7.0_eslint@8.36.0: + /eslint-plugin-jsonc@2.7.0(eslint@8.36.0): resolution: {integrity: sha512-DZgC71h/hZ9t5k/OGAKOMdJCleg2neZLL7No+YYi2ZMroCN4X5huZdrLf1USbrc6UTHwYujd1EDwXHg1qJ6CYw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: - '@eslint-community/eslint-utils': 4.3.0_eslint@8.36.0 + '@eslint-community/eslint-utils': 4.3.0(eslint@8.36.0) eslint: 8.36.0 jsonc-eslint-parser: 2.1.0 natural-compare: 1.4.0 - /eslint-plugin-jsx-a11y/6.7.1_eslint@8.36.0: + /eslint-plugin-jsx-a11y@6.7.1(eslint@8.36.0): resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} engines: {node: '>=4.0'} peerDependencies: @@ -5794,7 +6324,7 @@ packages: semver: 6.3.0 dev: true - /eslint-plugin-prettier/4.2.1_ose2zoovovx4ulolhifz3tfzx4: + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.6): resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -5806,11 +6336,11 @@ packages: optional: true dependencies: eslint: 8.36.0 - eslint-config-prettier: 8.8.0_eslint@8.36.0 + eslint-config-prettier: 8.8.0(eslint@8.36.0) prettier: 2.8.6 prettier-linter-helpers: 1.0.0 - /eslint-plugin-react-hooks/4.6.0_eslint@8.36.0: + /eslint-plugin-react-hooks@4.6.0(eslint@8.36.0): resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} engines: {node: '>=10'} peerDependencies: @@ -5819,7 +6349,7 @@ packages: eslint: 8.36.0 dev: true - /eslint-plugin-react/7.32.2_eslint@8.36.0: + /eslint-plugin-react@7.32.2(eslint@8.36.0): resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==} engines: {node: '>=4'} peerDependencies: @@ -5843,14 +6373,14 @@ packages: string.prototype.matchall: 4.0.8 dev: true - /eslint-plugin-simple-import-sort/10.0.0_eslint@8.36.0: + /eslint-plugin-simple-import-sort@10.0.0(eslint@8.36.0): resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} peerDependencies: eslint: '>=5.0.0' dependencies: eslint: 8.36.0 - /eslint-plugin-unused-imports/2.0.0_eslint@8.36.0: + /eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0): resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -5860,11 +6390,11 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: + '@typescript-eslint/eslint-plugin': 5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2) eslint: 8.36.0 eslint-rule-composer: 0.3.0 - dev: false - /eslint-plugin-unused-imports/2.0.0_pjgbsoxltfjhart6hcjsvw66hu: + /eslint-plugin-unused-imports@2.0.0(eslint@8.36.0): resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -5874,43 +6404,43 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.56.0_2hcjazgfnbtq42tcc73br2vup4 eslint: 8.36.0 eslint-rule-composer: 0.3.0 + dev: false - /eslint-rule-composer/0.3.0: + /eslint-rule-composer@0.3.0: resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} engines: {node: '>=4.0.0'} - /eslint-scope/5.1.1: + /eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} dependencies: esrecurse: 4.3.0 estraverse: 4.3.0 - /eslint-scope/7.1.1: + /eslint-scope@7.1.1: resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - /eslint-visitor-keys/2.1.0: + /eslint-visitor-keys@2.1.0: resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} engines: {node: '>=10'} dev: true - /eslint-visitor-keys/3.3.0: + /eslint-visitor-keys@3.3.0: resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /eslint/8.36.0: + /eslint@8.36.0: resolution: {integrity: sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.3.0_eslint@8.36.0 + '@eslint-community/eslint-utils': 4.3.0(eslint@8.36.0) '@eslint-community/regexpp': 4.4.0 '@eslint/eslintrc': 2.0.1 '@eslint/js': 8.36.0 @@ -5953,75 +6483,75 @@ packages: transitivePeerDependencies: - supports-color - /esno/0.16.3: + /esno@0.16.3: resolution: {integrity: sha512-6slSBEV1lMKcX13DBifvnDFpNno5WXhw4j/ff7RI0y51BZiDqEe5dNhhjhIQ3iCOQuzsm2MbVzmwqbN78BBhPg==} hasBin: true dependencies: tsx: 3.11.0 dev: true - /espree/9.4.1: + /espree@9.4.1: resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.8.1 - acorn-jsx: 5.3.2_acorn@8.8.1 + acorn: 8.8.2 + acorn-jsx: 5.3.2(acorn@8.8.2) eslint-visitor-keys: 3.3.0 dev: false - /espree/9.5.0: + /espree@9.5.0: resolution: {integrity: sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: acorn: 8.8.2 - acorn-jsx: 5.3.2_acorn@8.8.2 + acorn-jsx: 5.3.2(acorn@8.8.2) eslint-visitor-keys: 3.3.0 - /esprima/4.0.1: + /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - /esquery/1.5.0: + /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 - /esrecurse/4.3.0: + /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} dependencies: estraverse: 5.3.0 - /estraverse/4.3.0: + /estraverse@4.3.0: resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} engines: {node: '>=4.0'} - /estraverse/5.3.0: + /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - /estree-walker/0.6.1: + /estree-walker@0.6.1: resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} dev: false - /estree-walker/2.0.2: + /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - /esutils/2.0.3: + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - /eventemitter3/4.0.7: + /eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} dev: false - /extendable-error/0.1.7: + /extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} dev: true - /external-editor/3.1.0: + /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} dependencies: @@ -6030,13 +6560,13 @@ packages: tmp: 0.0.33 dev: true - /fast-deep-equal/3.1.3: + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - /fast-diff/1.2.0: + /fast-diff@1.2.0: resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - /fast-glob/3.2.12: + /fast-glob@3.2.12: resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} engines: {node: '>=8.6.0'} dependencies: @@ -6046,30 +6576,30 @@ packages: merge2: 1.4.1 micromatch: 4.0.5 - /fast-json-stable-stringify/2.1.0: + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - /fast-levenshtein/2.0.6: + /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - /fastq/1.13.0: + /fastq@1.13.0: resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} dependencies: reusify: 1.0.4 - /file-entry-cache/6.0.1: + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.0.4 - /fill-range/7.0.1: + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - /find-up/4.1.0: + /find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} dependencies: @@ -6077,31 +6607,31 @@ packages: path-exists: 4.0.0 dev: true - /find-up/5.0.0: + /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - /find-yarn-workspace-root2/1.2.16: + /find-yarn-workspace-root2@1.2.16: resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} dependencies: micromatch: 4.0.5 pkg-dir: 4.2.0 dev: true - /flat-cache/3.0.4: + /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flatted: 3.2.7 rimraf: 3.0.2 - /flatted/3.2.7: + /flatted@3.2.7: resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - /follow-redirects/1.15.2: + /follow-redirects@1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} peerDependencies: @@ -6110,12 +6640,12 @@ packages: debug: optional: true - /for-each/0.3.3: + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: is-callable: 1.2.7 - /form-data/4.0.0: + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} dependencies: @@ -6123,7 +6653,7 @@ packages: combined-stream: 1.0.8 mime-types: 2.1.35 - /fs-extra/10.1.0: + /fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} dependencies: @@ -6132,7 +6662,7 @@ packages: universalify: 2.0.0 dev: true - /fs-extra/7.0.1: + /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} dependencies: @@ -6141,7 +6671,7 @@ packages: universalify: 0.1.2 dev: true - /fs-extra/8.1.0: + /fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} dependencies: @@ -6150,20 +6680,20 @@ packages: universalify: 0.1.2 dev: true - /fs.realpath/1.0.0: + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents/2.3.2: + /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true optional: true - /function-bind/1.1.1: + /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - /function.prototype.name/1.1.5: + /function.prototype.name@1.1.5: resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} engines: {node: '>= 0.4'} dependencies: @@ -6172,64 +6702,64 @@ packages: es-abstract: 1.20.4 functions-have-names: 1.2.3 - /functions-have-names/1.2.3: + /functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - /generic-names/4.0.0: + /generic-names@4.0.0: resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} dependencies: loader-utils: 3.2.0 dev: false - /gensync/1.0.0-beta.2: + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} dev: true - /get-caller-file/2.0.5: + /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - /get-func-name/2.0.0: + /get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} - /get-intrinsic/1.2.0: + /get-intrinsic@1.2.0: resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} dependencies: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.3 - /get-source/2.0.12: + /get-source@2.0.12: resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} dependencies: data-uri-to-buffer: 2.0.2 source-map: 0.6.1 dev: false - /get-symbol-description/1.0.0: + /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.0 - /get-tsconfig/4.2.0: + /get-tsconfig@4.2.0: resolution: {integrity: sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==} - /glob-parent/5.1.2: + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - /glob-parent/6.0.2: + /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 - /glob/7.2.3: + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: fs.realpath: 1.0.0 @@ -6239,7 +6769,7 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 - /glob/8.0.3: + /glob@8.0.3: resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==} engines: {node: '>=12'} dependencies: @@ -6250,20 +6780,20 @@ packages: once: 1.4.0 dev: false - /globals/11.12.0: + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - /globals/13.19.0: + /globals@13.19.0: resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 - /globalyzer/0.1.0: + /globalyzer@0.1.0: resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} - /globby/11.1.0: + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} dependencies: @@ -6274,7 +6804,7 @@ packages: merge2: 1.4.1 slash: 3.0.0 - /globby/13.1.2: + /globby@13.1.2: resolution: {integrity: sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: @@ -6284,21 +6814,21 @@ packages: merge2: 1.4.1 slash: 4.0.0 - /globrex/0.1.2: + /globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - /gopd/1.0.1: + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.0 - /graceful-fs/4.2.10: + /graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - /grapheme-splitter/1.0.4: + /grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - /happy-dom/8.9.0: + /happy-dom@8.9.0: resolution: {integrity: sha512-JZwJuGdR7ko8L61136YzmrLv7LgTh5b8XaEM3P709mLjyQuXJ3zHTDXvUtBBahRjGlcYW0zGjIiEWizoTUGKfA==} dependencies: css.escape: 1.5.1 @@ -6312,74 +6842,74 @@ packages: - encoding dev: true - /hard-rejection/2.1.0: + /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} dev: true - /has-bigints/1.0.2: + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - /has-flag/3.0.0: + /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} - /has-flag/4.0.0: + /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-property-descriptors/1.0.0: + /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: get-intrinsic: 1.2.0 - /has-symbols/1.0.3: + /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} - /has-tostringtag/1.0.0: + /has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 - /has/1.0.3: + /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - /he/1.2.0: + /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true dev: true - /helpertypes/0.0.18: + /helpertypes@0.0.18: resolution: {integrity: sha512-XRhfbSEmR+poXUC5/8AbmYNJb2riOT6qPzjGJZr0S9YedHiaY+/tzPYzWMUclYMEdCYo/1l8PDYrQFCj02v97w==} engines: {node: '>=10.0.0'} dev: false - /hoist-non-react-statics/3.3.2: + /hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: react-is: 16.13.1 dev: true - /hosted-git-info/2.8.9: + /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true - /htm/3.1.1: + /htm@3.1.1: resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==} dev: false - /html-encoding-sniffer/3.0.0: + /html-encoding-sniffer@3.0.0: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} dependencies: whatwg-encoding: 2.0.0 - /htmlparser2/8.0.1: + /htmlparser2@8.0.1: resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==} dependencies: domelementtype: 2.3.0 @@ -6388,7 +6918,7 @@ packages: entities: 4.4.0 dev: true - /http-proxy-agent/5.0.0: + /http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} dependencies: @@ -6398,7 +6928,7 @@ packages: transitivePeerDependencies: - supports-color - /https-proxy-agent/5.0.1: + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} dependencies: @@ -6407,28 +6937,28 @@ packages: transitivePeerDependencies: - supports-color - /human-id/1.0.2: + /human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} dev: true - /iconv-lite/0.4.24: + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 dev: true - /iconv-lite/0.6.3: + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - /icss-replace-symbols/1.1.0: + /icss-replace-symbols@1.1.0: resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} dev: false - /icss-utils/5.1.0_postcss@8.4.20: + /icss-utils@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: @@ -6437,62 +6967,62 @@ packages: postcss: 8.4.20 dev: false - /ieee754/1.2.1: + /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} dev: false - /ignore/5.2.0: + /ignore@5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} - /immutable/4.1.0: + /immutable@4.1.0: resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} dev: false - /import-cwd/3.0.0: + /import-cwd@3.0.0: resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} engines: {node: '>=8'} dependencies: import-from: 3.0.0 dev: false - /import-fresh/3.3.0: + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - /import-from/3.0.0: + /import-from@3.0.0: resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==} engines: {node: '>=8'} dependencies: resolve-from: 5.0.0 dev: false - /imurmurhash/0.1.4: + /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - /indent-string/4.0.0: + /indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} dev: true - /inflight/1.0.6: + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: once: 1.4.0 wrappy: 1.0.2 - /inherits/2.0.4: + /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - /inspect-custom-symbol/1.1.1: + /inspect-custom-symbol@1.1.1: resolution: {integrity: sha512-GOucsp9EcdlLdhPUyOTvQDnbFJtp2WBWZV1Jqe+mVnkJQBL3w96+fB84C+JL+EKXOspMdB0eMDQPDp5w9fkfZA==} dev: false - /internal-slot/1.0.5: + /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} dependencies: @@ -6500,178 +7030,178 @@ packages: has: 1.0.3 side-channel: 1.0.4 - /interpret/1.4.0: + /interpret@1.4.0: resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} engines: {node: '>= 0.10'} - /invariant/2.2.4: + /invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} dependencies: loose-envify: 1.4.0 dev: false - /is-arguments/1.1.1: + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - /is-array-buffer/3.0.2: + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.0 is-typed-array: 1.1.10 - /is-arrayish/0.2.1: + /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - /is-bigint/1.0.4: + /is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: has-bigints: 1.0.2 - /is-binary-path/2.1.0: + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 dev: false - /is-boolean-object/1.1.2: + /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - /is-builtin-module/3.2.0: + /is-builtin-module@3.2.0: resolution: {integrity: sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==} engines: {node: '>=6'} dependencies: builtin-modules: 3.3.0 dev: false - /is-callable/1.2.7: + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - /is-ci/3.0.1: + /is-ci@3.0.1: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true dependencies: ci-info: 3.5.0 dev: true - /is-core-module/2.11.0: + /is-core-module@2.11.0: resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} dependencies: has: 1.0.3 - /is-date-object/1.0.5: + /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 - /is-docker/2.2.1: + /is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true - /is-extglob/2.1.1: + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - /is-fullwidth-code-point/3.0.0: + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - /is-fullwidth-code-point/4.0.0: + /is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} - /is-glob/4.0.3: + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - /is-map/2.0.2: + /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - /is-module/1.0.0: + /is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: false - /is-negative-zero/2.0.2: + /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} - /is-number-object/1.0.7: + /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 - /is-number/7.0.0: + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - /is-path-inside/3.0.3: + /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - /is-plain-obj/1.1.0: + /is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} dev: true - /is-potential-custom-element-name/1.0.1: + /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - /is-reference/1.2.1: + /is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: '@types/estree': 1.0.0 dev: false - /is-regex/1.1.4: + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - /is-set/2.0.2: + /is-set@2.0.2: resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - /is-shared-array-buffer/1.0.2: + /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: call-bind: 1.0.2 - /is-string/1.0.7: + /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 - /is-subdir/1.2.0: + /is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} dependencies: better-path-resolve: 1.0.0 dev: true - /is-symbol/1.0.4: + /is-symbol@1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 - /is-typed-array/1.1.10: + /is-typed-array@1.1.10: resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} engines: {node: '>= 0.4'} dependencies: @@ -6681,62 +7211,62 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 - /is-weakmap/2.0.1: + /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - /is-weakref/1.0.2: + /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 - /is-weakset/2.0.2: + /is-weakset@2.0.2: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.0 - /is-windows/1.0.2: + /is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} dev: true - /is-wsl/2.2.0: + /is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} dependencies: is-docker: 2.2.1 - /isarray/2.0.5: + /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - /isbot/3.4.5: + /isbot@3.4.5: resolution: {integrity: sha512-+KD6q1BBtw0iK9aGBGSfxJ31/ZgizKRjhm8ebgJUBMx0aeeQuIJ1I72beCoIrltIZGrSm4vmrxRxrG5n1aUTtw==} engines: {node: '>=12'} dev: false - /isexe/2.0.0: + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - /js-sdsl/4.1.5: + /js-sdsl@4.1.5: resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} - /js-tokens/4.0.0: + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - /js-yaml/3.14.1: + /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true dependencies: argparse: 1.0.10 esprima: 4.0.1 - /js-yaml/4.1.0: + /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true dependencies: argparse: 2.0.1 - /jsdom/20.0.3: + /jsdom@20.0.3: resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} engines: {node: '>=14'} peerDependencies: @@ -6776,7 +7306,7 @@ packages: - supports-color - utf-8-validate - /jsdom/21.1.1: + /jsdom@21.1.1: resolution: {integrity: sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w==} engines: {node: '>=14'} peerDependencies: @@ -6816,50 +7346,50 @@ packages: - supports-color - utf-8-validate - /jsesc/0.5.0: + /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true dev: true - /jsesc/2.5.2: + /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true - /jsesc/3.0.2: + /jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} hasBin: true dev: true - /json-parse-even-better-errors/2.3.1: + /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - /json-schema-traverse/0.4.1: + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - /json-stable-stringify-without-jsonify/1.0.1: + /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - /json5/1.0.1: + /json5@1.0.1: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: minimist: 1.2.7 - /json5/2.2.1: + /json5@2.2.1: resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} engines: {node: '>=6'} hasBin: true dev: false - /json5/2.2.3: + /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true dev: true - /jsonc-eslint-parser/2.1.0: + /jsonc-eslint-parser@2.1.0: resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: @@ -6868,16 +7398,16 @@ packages: espree: 9.5.0 semver: 7.3.8 - /jsonc-parser/3.2.0: + /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - /jsonfile/4.0.0: + /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: graceful-fs: 4.2.10 dev: true - /jsonfile/6.1.0: + /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: universalify: 2.0.0 @@ -6885,7 +7415,7 @@ packages: graceful-fs: 4.2.10 dev: true - /jsx-ast-utils/3.3.3: + /jsx-ast-utils@3.3.3: resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} engines: {node: '>=4.0'} dependencies: @@ -6893,57 +7423,57 @@ packages: object.assign: 4.1.4 dev: true - /just-flatten-it/2.2.1: + /just-flatten-it@2.2.1: resolution: {integrity: sha512-VwvlzikphspzZL38LiZpoBsFGQy6MnmXYekBeZA8lSNwgSC87zA3a93bCZKkDuOM+djMZhfjd3lXAZyxficKCg==} dev: false - /just-zip-it/2.3.1: + /just-zip-it@2.3.1: resolution: {integrity: sha512-h8Y3DAVTZRP3Weq7btWYfkYHQGhxiuKzfOO7Ec+x8XaDcBvbOsC2jIdezC6tEzbt+A4fTJTREnj3gF5DyMkFfw==} dev: false - /kind-of/6.0.3: + /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} dev: true - /kleur/4.1.5: + /kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} dev: true - /language-subtag-registry/0.3.22: + /language-subtag-registry@0.3.22: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: true - /language-tags/1.0.5: + /language-tags@1.0.5: resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==} dependencies: language-subtag-registry: 0.3.22 dev: true - /levn/0.3.0: + /levn@0.3.0: resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.1.2 type-check: 0.3.2 - /levn/0.4.1: + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - /lilconfig/2.0.6: + /lilconfig@2.0.6: resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} engines: {node: '>=10'} dev: false - /lines-and-columns/1.2.4: + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - /load-yaml-file/0.2.0: + /load-yaml-file@0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'} dependencies: @@ -6953,128 +7483,128 @@ packages: strip-bom: 3.0.0 dev: true - /loader-utils/3.2.0: + /loader-utils@3.2.0: resolution: {integrity: sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==} engines: {node: '>= 12.13.0'} dev: false - /local-pkg/0.4.2: + /local-pkg@0.4.2: resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} engines: {node: '>=14'} - /locate-path/5.0.0: + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} dependencies: p-locate: 4.1.0 dev: true - /locate-path/6.0.0: + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} dependencies: p-locate: 5.0.0 - /lodash.camelcase/4.3.0: + /lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: false - /lodash.debounce/4.0.8: + /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} dev: true - /lodash.memoize/4.1.2: + /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} dev: false - /lodash.merge/4.6.2: + /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - /lodash.startcase/4.4.0: + /lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} dev: true - /lodash.uniq/4.5.0: + /lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} dev: false - /lodash/4.17.21: + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - /loose-envify/1.4.0: + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true dependencies: js-tokens: 4.0.0 - /loupe/2.3.6: + /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} dependencies: get-func-name: 2.0.0 - /lru-cache/4.1.5: + /lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} dependencies: pseudomap: 1.0.2 yallist: 2.1.2 dev: true - /lru-cache/5.1.1: + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 dev: true - /lru-cache/6.0.0: + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} dependencies: yallist: 4.0.0 - /lz-string/1.4.4: + /lz-string@1.4.4: resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} hasBin: true dev: false - /lz-string/1.5.0: + /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true dev: true - /magic-string/0.25.9: + /magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} dependencies: sourcemap-codec: 1.4.8 dev: false - /magic-string/0.26.7: + /magic-string@0.26.7: resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} engines: {node: '>=12'} dependencies: sourcemap-codec: 1.4.8 - /magic-string/0.27.0: + /magic-string@0.27.0: resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.14 dev: false - /map-obj/1.0.1: + /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} dev: true - /map-obj/4.3.0: + /map-obj@4.3.0: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} dev: true - /mdn-data/2.0.14: + /mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} dev: false - /meow/6.1.1: + /meow@6.1.1: resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} engines: {node: '>=8'} dependencies: @@ -7091,45 +7621,45 @@ packages: yargs-parser: 18.1.3 dev: true - /merge2/1.4.1: + /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - /micromatch/4.0.5: + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} dependencies: braces: 3.0.2 picomatch: 2.3.1 - /mime-db/1.52.0: + /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - /mime-types/2.1.35: + /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 - /min-indent/1.0.1: + /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} dev: true - /minimatch/3.1.2: + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - /minimatch/5.1.0: + /minimatch@5.1.0: resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 dev: false - /minimist-options/4.1.0: + /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} dependencies: @@ -7138,15 +7668,15 @@ packages: kind-of: 6.0.3 dev: true - /minimist/1.2.7: + /minimist@1.2.7: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - /mixme/0.5.4: + /mixme@0.5.4: resolution: {integrity: sha512-3KYa4m4Vlqx98GPdOHghxSdNtTvcP8E0kkaJ5Dlh+h2DRzF7zpuVVcA8B0QpKd11YJeP9QQ7ASkKzOeu195Wzw==} engines: {node: '>= 8.0.0'} dev: true - /mlly/1.2.0: + /mlly@1.2.0: resolution: {integrity: sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==} dependencies: acorn: 8.8.2 @@ -7154,22 +7684,22 @@ packages: pkg-types: 1.0.2 ufo: 1.1.1 - /mrmime/1.0.1: + /mrmime@1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} engines: {node: '>=10'} dev: true - /ms/2.0.0: + /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: true - /ms/2.1.2: + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - /ms/2.1.3: + /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - /multimatch/5.0.0: + /multimatch@5.0.0: resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} engines: {node: '>=10'} dependencies: @@ -7180,22 +7710,22 @@ packages: minimatch: 3.1.2 dev: false - /nan/2.17.0: + /nan@2.17.0: resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} dev: false - /nanoid/3.3.4: + /nanoid@3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /natural-compare-lite/1.4.0: + /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - /natural-compare/1.4.0: + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - /node-fetch/2.6.7: + /node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} peerDependencies: @@ -7207,17 +7737,17 @@ packages: whatwg-url: 5.0.0 dev: true - /node-pty/0.10.1: + /node-pty@0.10.1: resolution: {integrity: sha512-JTdtUS0Im/yRsWJSx7yiW9rtpfmxqxolrtnyKwPLI+6XqTAPW/O2MjS8FYL4I5TsMbH2lVgDb2VMjp+9LoQGNg==} requiresBuild: true dependencies: nan: 2.17.0 dev: false - /node-releases/2.0.6: + /node-releases@2.0.6: resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} - /normalize-package-data/2.5.0: + /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 @@ -7226,48 +7756,48 @@ packages: validate-npm-package-license: 3.0.4 dev: true - /normalize-path/3.0.0: + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} dev: false - /normalize-url/6.1.0: + /normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} dev: false - /nth-check/2.1.1: + /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: boolbase: 1.0.0 - /nwsapi/2.2.2: + /nwsapi@2.2.2: resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} - /object-assign/4.1.1: + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-inspect/1.12.3: + /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - /object-is/1.1.5: + /object-is@1.1.5: resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - /object-keys/1.1.1: + /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - /object-path/0.11.8: + /object-path@0.11.8: resolution: {integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==} engines: {node: '>= 10.12.0'} dev: false - /object.assign/4.1.4: + /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} engines: {node: '>= 0.4'} dependencies: @@ -7276,7 +7806,7 @@ packages: has-symbols: 1.0.3 object-keys: 1.1.1 - /object.entries/1.1.6: + /object.entries@1.1.6: resolution: {integrity: sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==} engines: {node: '>= 0.4'} dependencies: @@ -7285,7 +7815,7 @@ packages: es-abstract: 1.20.4 dev: true - /object.fromentries/2.0.6: + /object.fromentries@2.0.6: resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} engines: {node: '>= 0.4'} dependencies: @@ -7294,14 +7824,14 @@ packages: es-abstract: 1.20.4 dev: true - /object.hasown/1.1.2: + /object.hasown@1.1.2: resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} dependencies: define-properties: 1.2.0 es-abstract: 1.20.4 dev: true - /object.values/1.1.6: + /object.values@1.1.6: resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} engines: {node: '>= 0.4'} dependencies: @@ -7309,12 +7839,12 @@ packages: define-properties: 1.2.0 es-abstract: 1.20.4 - /once/1.4.0: + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - /open/8.4.0: + /open@8.4.0: resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} engines: {node: '>=12'} dependencies: @@ -7322,7 +7852,7 @@ packages: is-docker: 2.2.1 is-wsl: 2.2.0 - /optionator/0.8.3: + /optionator@0.8.3: resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} engines: {node: '>= 0.8.0'} dependencies: @@ -7333,7 +7863,7 @@ packages: type-check: 0.3.2 word-wrap: 1.2.3 - /optionator/0.9.1: + /optionator@0.9.1: resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} engines: {node: '>= 0.8.0'} dependencies: @@ -7344,65 +7874,65 @@ packages: type-check: 0.4.0 word-wrap: 1.2.3 - /os-tmpdir/1.0.2: + /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} dev: true - /outdent/0.5.0: + /outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} dev: true - /p-filter/2.1.0: + /p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} dependencies: p-map: 2.1.0 dev: true - /p-finally/1.0.0: + /p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} dev: false - /p-limit/2.3.0: + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} dependencies: p-try: 2.2.0 dev: true - /p-limit/3.1.0: + /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 - /p-limit/4.0.0: + /p-limit@4.0.0: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: yocto-queue: 1.0.0 - /p-locate/4.1.0: + /p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} dependencies: p-limit: 2.3.0 dev: true - /p-locate/5.0.0: + /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 - /p-map/2.1.0: + /p-map@2.1.0: resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} engines: {node: '>=6'} dev: true - /p-queue/6.6.2: + /p-queue@6.6.2: resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} engines: {node: '>=8'} dependencies: @@ -7410,25 +7940,25 @@ packages: p-timeout: 3.2.0 dev: false - /p-timeout/3.2.0: + /p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} engines: {node: '>=8'} dependencies: p-finally: 1.0.0 dev: false - /p-try/2.2.0: + /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} dev: true - /parent-module/1.0.1: + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} dependencies: callsites: 3.1.0 - /parse-json/5.2.0: + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: @@ -7437,86 +7967,86 @@ packages: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - /parse5-htmlparser2-tree-adapter/7.0.0: + /parse5-htmlparser2-tree-adapter@7.0.0: resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} dependencies: domhandler: 5.0.3 parse5: 7.1.2 dev: true - /parse5/7.1.1: + /parse5@7.1.1: resolution: {integrity: sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==} dependencies: entities: 4.4.0 - /parse5/7.1.2: + /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: entities: 4.4.0 - /path-exists/4.0.0: + /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - /path-is-absolute/1.0.1: + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - /path-key/3.1.1: + /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - /path-parse/1.0.7: + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - /path-type/4.0.0: + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - /pathe/1.1.0: + /pathe@1.1.0: resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} - /pathval/1.1.1: + /pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - /picocolors/1.0.0: + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - /picomatch/2.3.1: + /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - /pify/4.0.1: + /pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} dev: true - /pify/5.0.0: + /pify@5.0.0: resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} engines: {node: '>=10'} dev: false - /pkg-dir/4.2.0: + /pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} dependencies: find-up: 4.1.0 dev: true - /pkg-types/1.0.2: + /pkg-types@1.0.2: resolution: {integrity: sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==} dependencies: jsonc-parser: 3.2.0 mlly: 1.2.0 pathe: 1.1.0 - /please-upgrade-node/3.2.0: + /please-upgrade-node@3.2.0: resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} dependencies: semver-compare: 1.0.0 dev: false - /postcss-calc/8.2.4_postcss@8.4.20: + /postcss-calc@8.2.4(postcss@8.4.20): resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} peerDependencies: postcss: ^8.2.2 @@ -7526,7 +8056,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-colormin/5.3.0_postcss@8.4.20: + /postcss-colormin@5.3.0(postcss@8.4.20): resolution: {integrity: sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7539,7 +8069,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-convert-values/5.1.3_postcss@8.4.20: + /postcss-convert-values@5.1.3(postcss@8.4.20): resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7550,7 +8080,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-discard-comments/5.1.2_postcss@8.4.20: + /postcss-discard-comments@5.1.2(postcss@8.4.20): resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7559,7 +8089,7 @@ packages: postcss: 8.4.20 dev: false - /postcss-discard-duplicates/5.1.0_postcss@8.4.20: + /postcss-discard-duplicates@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7568,7 +8098,7 @@ packages: postcss: 8.4.20 dev: false - /postcss-discard-empty/5.1.1_postcss@8.4.20: + /postcss-discard-empty@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7577,7 +8107,7 @@ packages: postcss: 8.4.20 dev: false - /postcss-discard-overridden/5.1.0_postcss@8.4.20: + /postcss-discard-overridden@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7586,7 +8116,7 @@ packages: postcss: 8.4.20 dev: false - /postcss-load-config/3.1.4_postcss@8.4.20: + /postcss-load-config@3.1.4(postcss@8.4.20): resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} peerDependencies: @@ -7603,7 +8133,7 @@ packages: yaml: 1.10.2 dev: false - /postcss-merge-longhand/5.1.7_postcss@8.4.20: + /postcss-merge-longhand@5.1.7(postcss@8.4.20): resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7611,10 +8141,10 @@ packages: dependencies: postcss: 8.4.20 postcss-value-parser: 4.2.0 - stylehacks: 5.1.1_postcss@8.4.20 + stylehacks: 5.1.1(postcss@8.4.20) dev: false - /postcss-merge-rules/5.1.3_postcss@8.4.20: + /postcss-merge-rules@5.1.3(postcss@8.4.20): resolution: {integrity: sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7622,12 +8152,12 @@ packages: dependencies: browserslist: 4.21.4 caniuse-api: 3.0.0 - cssnano-utils: 3.1.0_postcss@8.4.20 + cssnano-utils: 3.1.0(postcss@8.4.20) postcss: 8.4.20 postcss-selector-parser: 6.0.10 dev: false - /postcss-minify-font-values/5.1.0_postcss@8.4.20: + /postcss-minify-font-values@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7637,31 +8167,31 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-minify-gradients/5.1.1_postcss@8.4.20: + /postcss-minify-gradients@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: colord: 2.9.3 - cssnano-utils: 3.1.0_postcss@8.4.20 + cssnano-utils: 3.1.0(postcss@8.4.20) postcss: 8.4.20 postcss-value-parser: 4.2.0 dev: false - /postcss-minify-params/5.1.4_postcss@8.4.20: + /postcss-minify-params@5.1.4(postcss@8.4.20): resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: browserslist: 4.21.4 - cssnano-utils: 3.1.0_postcss@8.4.20 + cssnano-utils: 3.1.0(postcss@8.4.20) postcss: 8.4.20 postcss-value-parser: 4.2.0 dev: false - /postcss-minify-selectors/5.2.1_postcss@8.4.20: + /postcss-minify-selectors@5.2.1(postcss@8.4.20): resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7671,7 +8201,7 @@ packages: postcss-selector-parser: 6.0.10 dev: false - /postcss-modules-extract-imports/3.0.0_postcss@8.4.20: + /postcss-modules-extract-imports@3.0.0(postcss@8.4.20): resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: @@ -7680,19 +8210,19 @@ packages: postcss: 8.4.20 dev: false - /postcss-modules-local-by-default/4.0.0_postcss@8.4.20: + /postcss-modules-local-by-default@4.0.0(postcss@8.4.20): resolution: {integrity: sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - icss-utils: 5.1.0_postcss@8.4.20 + icss-utils: 5.1.0(postcss@8.4.20) postcss: 8.4.20 postcss-selector-parser: 6.0.10 postcss-value-parser: 4.2.0 dev: false - /postcss-modules-scope/3.0.0_postcss@8.4.20: + /postcss-modules-scope@3.0.0(postcss@8.4.20): resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: @@ -7702,17 +8232,17 @@ packages: postcss-selector-parser: 6.0.10 dev: false - /postcss-modules-values/4.0.0_postcss@8.4.20: + /postcss-modules-values@4.0.0(postcss@8.4.20): resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} engines: {node: ^10 || ^12 || >= 14} peerDependencies: postcss: ^8.1.0 dependencies: - icss-utils: 5.1.0_postcss@8.4.20 + icss-utils: 5.1.0(postcss@8.4.20) postcss: 8.4.20 dev: false - /postcss-modules/4.3.1_postcss@8.4.20: + /postcss-modules@4.3.1(postcss@8.4.20): resolution: {integrity: sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==} peerDependencies: postcss: ^8.0.0 @@ -7721,14 +8251,14 @@ packages: icss-replace-symbols: 1.1.0 lodash.camelcase: 4.3.0 postcss: 8.4.20 - postcss-modules-extract-imports: 3.0.0_postcss@8.4.20 - postcss-modules-local-by-default: 4.0.0_postcss@8.4.20 - postcss-modules-scope: 3.0.0_postcss@8.4.20 - postcss-modules-values: 4.0.0_postcss@8.4.20 + postcss-modules-extract-imports: 3.0.0(postcss@8.4.20) + postcss-modules-local-by-default: 4.0.0(postcss@8.4.20) + postcss-modules-scope: 3.0.0(postcss@8.4.20) + postcss-modules-values: 4.0.0(postcss@8.4.20) string-hash: 1.1.3 dev: false - /postcss-normalize-charset/5.1.0_postcss@8.4.20: + /postcss-normalize-charset@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7737,7 +8267,7 @@ packages: postcss: 8.4.20 dev: false - /postcss-normalize-display-values/5.1.0_postcss@8.4.20: + /postcss-normalize-display-values@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7747,7 +8277,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-positions/5.1.1_postcss@8.4.20: + /postcss-normalize-positions@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7757,7 +8287,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-repeat-style/5.1.1_postcss@8.4.20: + /postcss-normalize-repeat-style@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7767,7 +8297,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-string/5.1.0_postcss@8.4.20: + /postcss-normalize-string@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7777,7 +8307,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-timing-functions/5.1.0_postcss@8.4.20: + /postcss-normalize-timing-functions@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7787,7 +8317,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-unicode/5.1.1_postcss@8.4.20: + /postcss-normalize-unicode@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7798,7 +8328,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-url/5.1.0_postcss@8.4.20: + /postcss-normalize-url@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7809,7 +8339,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-whitespace/5.1.1_postcss@8.4.20: + /postcss-normalize-whitespace@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7819,18 +8349,18 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-ordered-values/5.1.3_postcss@8.4.20: + /postcss-ordered-values@5.1.3(postcss@8.4.20): resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: - cssnano-utils: 3.1.0_postcss@8.4.20 + cssnano-utils: 3.1.0(postcss@8.4.20) postcss: 8.4.20 postcss-value-parser: 4.2.0 dev: false - /postcss-reduce-initial/5.1.1_postcss@8.4.20: + /postcss-reduce-initial@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7841,7 +8371,7 @@ packages: postcss: 8.4.20 dev: false - /postcss-reduce-transforms/5.1.0_postcss@8.4.20: + /postcss-reduce-transforms@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7851,7 +8381,7 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-selector-parser/6.0.10: + /postcss-selector-parser@6.0.10: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} engines: {node: '>=4'} dependencies: @@ -7859,7 +8389,7 @@ packages: util-deprecate: 1.0.2 dev: false - /postcss-svgo/5.1.0_postcss@8.4.20: + /postcss-svgo@5.1.0(postcss@8.4.20): resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7870,7 +8400,7 @@ packages: svgo: 2.8.0 dev: false - /postcss-unique-selectors/5.1.1_postcss@8.4.20: + /postcss-unique-selectors@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -7880,10 +8410,10 @@ packages: postcss-selector-parser: 6.0.10 dev: false - /postcss-value-parser/4.2.0: + /postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - /postcss/8.4.20: + /postcss@8.4.20: resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==} engines: {node: ^10 || ^12 || >=14} dependencies: @@ -7892,7 +8422,7 @@ packages: source-map-js: 1.0.2 dev: false - /postcss/8.4.21: + /postcss@8.4.21: resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} engines: {node: ^10 || ^12 || >=14} dependencies: @@ -7900,7 +8430,7 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 - /preact-render-to-string/5.2.6_preact@10.11.3: + /preact-render-to-string@5.2.6(preact@10.11.3): resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} peerDependencies: preact: '>=10' @@ -7909,10 +8439,10 @@ packages: pretty-format: 3.8.0 dev: true - /preact/10.11.3: + /preact@10.11.3: resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} - /preferred-pm/3.0.3: + /preferred-pm@3.0.3: resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} engines: {node: '>=10'} dependencies: @@ -7922,32 +8452,32 @@ packages: which-pm: 2.0.0 dev: true - /prelude-ls/1.1.2: + /prelude-ls@1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} - /prelude-ls/1.2.1: + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - /prettier-linter-helpers/1.0.0: + /prettier-linter-helpers@1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} dependencies: fast-diff: 1.2.0 - /prettier/2.8.1: + /prettier@2.8.1: resolution: {integrity: sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==} engines: {node: '>=10.13.0'} hasBin: true dev: false - /prettier/2.8.6: + /prettier@2.8.6: resolution: {integrity: sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==} engines: {node: '>=10.13.0'} hasBin: true - /pretty-format/27.5.1: + /pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: @@ -7955,72 +8485,72 @@ packages: ansi-styles: 5.2.0 react-is: 17.0.2 - /pretty-format/3.8.0: + /pretty-format@3.8.0: resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} dev: true - /printable-characters/1.0.42: + /printable-characters@1.0.42: resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} dev: false - /promise.series/0.2.0: + /promise.series@0.2.0: resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} engines: {node: '>=0.12'} dev: false - /prop-types/15.8.1: + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 - /proxy-from-env/1.1.0: + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - /pseudomap/1.0.2: + /pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} dev: true - /psl/1.9.0: + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - /punycode/2.1.1: + /punycode@2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} - /punycode/2.3.0: + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} - /purecss/3.0.0: + /purecss@3.0.0: resolution: {integrity: sha512-IdYbGwbmuA7Hy9ACIO1q7ks4xGLcJSVHxJT2BXIz2c4Ve1aSrNU5bAzA1ILT4Gmdy5K59ruWoRPf9WvJZU5fbA==} dev: false - /q/1.5.1: + /q@1.5.1: resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} dev: true - /query-ast/1.0.4: + /query-ast@1.0.4: resolution: {integrity: sha512-KFJFSvODCBjIH5HbHvITj9EEZKYUU6VX0T5CuB1ayvjUoUaZkKMi6eeby5Tf8DMukyZHlJQOE1+f3vevKUe6eg==} dependencies: invariant: 2.2.4 lodash: 4.17.21 dev: false - /querystringify/2.2.0: + /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - /queue-microtask/1.2.3: + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - /quick-lru/4.0.1: + /quick-lru@4.0.1: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} engines: {node: '>=8'} dev: true - /react-dom/18.2.0_react@18.2.0: + /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: react: '*' @@ -8029,7 +8559,7 @@ packages: react: 18.2.0 scheduler: 0.23.0 - /react-error-boundary/3.1.4_react@18.2.0: + /react-error-boundary@3.1.4(react@18.2.0): resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==} engines: {node: '>=10', npm: '>=6'} peerDependencies: @@ -8039,17 +8569,17 @@ packages: react: 18.2.0 dev: false - /react-fast-compare/3.2.0: + /react-fast-compare@3.2.0: resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==} dev: true - /react-is/16.13.1: + /react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - /react-is/17.0.2: + /react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - /react-portal/4.2.2_biqbaboplfbrettd7655fr4n2y: + /react-portal@4.2.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-vS18idTmevQxyQpnde0Td6ZcUlv+pD8GTyR42n3CHUQq9OHi1C4jDE4ZWEbEsrbrLRhSECYiao58cvocwMtP7Q==} peerDependencies: react: '*' @@ -8057,15 +8587,15 @@ packages: dependencies: prop-types: 15.8.1 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: false - /react-refresh/0.13.0: + /react-refresh@0.13.0: resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==} engines: {node: '>=0.10.0'} dev: true - /react-transition-group/4.4.5_biqbaboplfbrettd7655fr4n2y: + /react-transition-group@4.4.5(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: react: '*' @@ -8076,16 +8606,16 @@ packages: loose-envify: 1.4.0 prop-types: 15.8.1 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: true - /react/18.2.0: + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 - /read-pkg-up/7.0.1: + /read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} dependencies: @@ -8094,7 +8624,7 @@ packages: type-fest: 0.8.1 dev: true - /read-pkg/5.2.0: + /read-pkg@5.2.0: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} dependencies: @@ -8104,7 +8634,7 @@ packages: type-fest: 0.6.0 dev: true - /read-yaml-file/1.1.0: + /read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} dependencies: @@ -8114,20 +8644,20 @@ packages: strip-bom: 3.0.0 dev: true - /readdirp/3.6.0: + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 dev: false - /rechoir/0.6.2: + /rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} engines: {node: '>= 0.10'} dependencies: resolve: 1.22.1 - /redent/3.0.0: + /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} dependencies: @@ -8135,27 +8665,27 @@ packages: strip-indent: 3.0.0 dev: true - /regenerate-unicode-properties/10.1.0: + /regenerate-unicode-properties@10.1.0: resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} engines: {node: '>=4'} dependencies: regenerate: 1.4.2 dev: true - /regenerate/1.4.2: + /regenerate@1.4.2: resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} dev: true - /regenerator-runtime/0.13.11: + /regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - /regenerator-transform/0.15.0: + /regenerator-transform@0.15.0: resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} dependencies: '@babel/runtime': 7.21.0 dev: true - /regexp.prototype.flags/1.4.3: + /regexp.prototype.flags@1.4.3: resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} engines: {node: '>= 0.4'} dependencies: @@ -8163,7 +8693,7 @@ packages: define-properties: 1.2.0 functions-have-names: 1.2.3 - /regexpu-core/5.2.1: + /regexpu-core@5.2.1: resolution: {integrity: sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==} engines: {node: '>=4'} dependencies: @@ -8175,41 +8705,41 @@ packages: unicode-match-property-value-ecmascript: 2.0.0 dev: true - /regjsgen/0.7.1: + /regjsgen@0.7.1: resolution: {integrity: sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==} dev: true - /regjsparser/0.9.1: + /regjsparser@0.9.1: resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} hasBin: true dependencies: jsesc: 0.5.0 dev: true - /require-directory/2.1.1: + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - /require-main-filename/2.0.0: + /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} dev: true - /require-package-name/2.0.1: + /require-package-name@2.0.1: resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} dev: false - /requires-port/1.0.0: + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - /resolve-from/4.0.0: + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - /resolve-from/5.0.0: + /resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - /resolve/1.22.1: + /resolve@1.22.1: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true dependencies: @@ -8217,7 +8747,7 @@ packages: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - /resolve/2.0.0-next.4: + /resolve@2.0.0-next.4: resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} hasBin: true dependencies: @@ -8226,26 +8756,26 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true - /reusify/1.0.4: + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - /rimraf/3.0.2: + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.3 - /rollup-plugin-polyfill-node/0.11.0_rollup@3.9.1: + /rollup-plugin-polyfill-node@0.11.0(rollup@3.9.1): resolution: {integrity: sha512-5t+qhq4LAQKQBgbPOQJEoxxGzU5b+zLfvzpUAGy9u0MCMs8y+mrjUAv8+xrkWdxnwXQwJtjmCMnA9lCflsMzNw==} peerDependencies: rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 dependencies: - '@rollup/plugin-inject': 5.0.2_rollup@3.9.1 + '@rollup/plugin-inject': 5.0.2(rollup@3.9.1) rollup: 3.9.1 dev: false - /rollup-plugin-postcss/4.0.2_postcss@8.4.20: + /rollup-plugin-postcss@4.0.2(postcss@8.4.20): resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==} engines: {node: '>=10'} peerDependencies: @@ -8253,13 +8783,13 @@ packages: dependencies: chalk: 4.1.2 concat-with-sourcemaps: 1.1.0 - cssnano: 5.1.14_postcss@8.4.20 + cssnano: 5.1.14(postcss@8.4.20) import-cwd: 3.0.0 p-queue: 6.6.2 pify: 5.0.0 postcss: 8.4.20 - postcss-load-config: 3.1.4_postcss@8.4.20 - postcss-modules: 4.3.1_postcss@8.4.20 + postcss-load-config: 3.1.4(postcss@8.4.20) + postcss-modules: 4.3.1(postcss@8.4.20) promise.series: 0.2.0 resolve: 1.22.1 rollup-pluginutils: 2.8.2 @@ -8269,7 +8799,7 @@ packages: - ts-node dev: false - /rollup-plugin-ts/3.0.2_tumybvdr6br7dr3yffpdihdhou: + /rollup-plugin-ts@3.0.2(rollup@3.9.1)(typescript@5.0.2): resolution: {integrity: sha512-67qi2QTHewhLyKDG6fX3jpohWpmUPPIT/xJ7rsYK46X6MqmoWy64Ti0y8ygPfLv8mXDCdRZUofM3mTxDfCswRA==} engines: {node: '>=14.9.0', npm: '>=7.0.0', pnpm: '>=3.2.0', yarn: '>=1.13'} peerDependencies: @@ -8303,57 +8833,57 @@ packages: ansi-colors: 4.1.3 browserslist: 4.21.4 browserslist-generator: 1.0.66 - compatfactory: 1.0.1_typescript@5.0.2 + compatfactory: 1.0.1(typescript@5.0.2) crosspath: 2.0.0 magic-string: 0.26.7 rollup: 3.9.1 - ts-clone-node: 1.0.0_typescript@5.0.2 + ts-clone-node: 1.0.0(typescript@5.0.2) tslib: 2.5.0 typescript: 5.0.2 dev: false - /rollup-pluginutils/2.8.2: + /rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} dependencies: estree-walker: 0.6.1 dev: false - /rollup/3.9.1: + /rollup@3.9.1: resolution: {integrity: sha512-GswCYHXftN8ZKGVgQhTFUJB/NBXxrRGgO2NCy6E8s1rwEJ4Q9/VttNqcYfEvx4dTo4j58YqdC3OVztPzlKSX8w==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: fsevents: 2.3.2 - /rrweb-cssom/0.6.0: + /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} - /run-parallel/1.2.0: + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - /rxjs/7.5.7: + /rxjs@7.5.7: resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} dependencies: tslib: 2.5.0 dev: true - /safe-identifier/0.4.2: + /safe-identifier@0.4.2: resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} dev: false - /safe-regex-test/1.0.0: + /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.0 is-regex: 1.1.4 - /safer-buffer/2.1.2: + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - /sass/1.56.0: + /sass@1.56.0: resolution: {integrity: sha512-WFJ9XrpkcnqZcYuLRJh5qiV6ibQOR4AezleeEjTjMsCocYW59dEG19U3fwTTXxzi2Ed3yjPBp727hbbj53pHFw==} engines: {node: '>=12.0.0'} hasBin: true @@ -8363,18 +8893,18 @@ packages: source-map-js: 1.0.2 dev: false - /saxes/6.0.0: + /saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} dependencies: xmlchars: 2.2.0 - /scheduler/0.23.0: + /scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: loose-envify: 1.4.0 - /scss-parser/1.0.5: + /scss-parser@1.0.5: resolution: {integrity: sha512-RZOtvCmCnwkDo7kdcYBi807Y5EoTIxJ34AgEgJNDmOH1jl0/xG0FyYZFbH6Ga3Iwu7q8LSdxJ4C5UkzNXjQxKQ==} engines: {node: '>=6.0.0'} dependencies: @@ -8382,57 +8912,57 @@ packages: lodash: 4.17.21 dev: false - /semver-compare/1.0.0: + /semver-compare@1.0.0: resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} dev: false - /semver/5.7.1: + /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true dev: true - /semver/6.3.0: + /semver@6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - /semver/7.3.8: + /semver@7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 - /set-blocking/2.0.0: + /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true - /shallowequal/1.1.0: + /shallowequal@1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} dev: true - /shebang-command/1.2.0: + /shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} dependencies: shebang-regex: 1.0.0 dev: true - /shebang-command/2.0.0: + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - /shebang-regex/1.0.0: + /shebang-regex@1.0.0: resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} engines: {node: '>=0.10.0'} dev: true - /shebang-regex/3.0.0: + /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - /shell-escape-tag/2.0.2: + /shell-escape-tag@2.0.2: resolution: {integrity: sha512-kqmtJG6VzTahZl8Y3384ldskA9rzoEMdXLoMEBAq9334/UDdmfWl3OtmrGJPlVcyXvcSy3poDKka57gMxskMPw==} dependencies: any-shell-escape: 0.1.1 @@ -8441,11 +8971,11 @@ packages: just-zip-it: 2.3.1 dev: false - /shell-split/1.0.0: + /shell-split@1.0.0: resolution: {integrity: sha512-BtLZmM1cw526/KegtJlBV21RdNEKweM0UuGKHEJPOi2GTByOw5T8N2L0dYC5P25z6wLAP3rm0W7kvm0e1MybVg==} dev: false - /shelljs/0.8.5: + /shelljs@0.8.5: resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} engines: {node: '>=4'} hasBin: true @@ -8454,21 +8984,21 @@ packages: interpret: 1.4.0 rechoir: 0.6.2 - /side-channel/1.0.4: + /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.0 object-inspect: 1.12.3 - /siginfo/2.0.0: + /siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - /signal-exit/3.0.7: + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true - /sirv/2.0.2: + /sirv@2.0.2: resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==} engines: {node: '>= 10'} dependencies: @@ -8477,22 +9007,22 @@ packages: totalist: 3.0.0 dev: true - /slash/3.0.0: + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - /slash/4.0.0: + /slash@4.0.0: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} - /slice-ansi/5.0.0: + /slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 - /smartwrap/2.0.2: + /smartwrap@2.0.2: resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} engines: {node: '>=6'} hasBin: true @@ -8505,102 +9035,102 @@ packages: yargs: 15.4.1 dev: true - /source-map-js/1.0.2: + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - /source-map-support/0.5.21: + /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: buffer-from: 1.1.2 source-map: 0.6.1 dev: true - /source-map/0.6.1: + /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - /sourcemap-codec/1.4.8: + /sourcemap-codec@1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead - /spawndamnit/2.0.0: + /spawndamnit@2.0.0: resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} dependencies: cross-spawn: 5.1.0 signal-exit: 3.0.7 dev: true - /spdx-correct/3.1.1: + /spdx-correct@3.1.1: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.12 dev: true - /spdx-exceptions/2.3.0: + /spdx-exceptions@2.3.0: resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} dev: true - /spdx-expression-parse/3.0.1: + /spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} dependencies: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.12 dev: true - /spdx-license-ids/3.0.12: + /spdx-license-ids@3.0.12: resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} dev: true - /split2/4.1.0: + /split2@4.1.0: resolution: {integrity: sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==} engines: {node: '>= 10.x'} dev: false - /sprintf-js/1.0.3: + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - /stable/0.1.8: + /stable@0.1.8: resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' dev: false - /stackback/0.0.2: + /stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - /stacktracey/2.1.8: + /stacktracey@2.1.8: resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} dependencies: as-table: 1.0.55 get-source: 2.0.12 dev: false - /std-env/3.3.2: + /std-env@3.3.2: resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} - /stop-iteration-iterator/1.0.0: + /stop-iteration-iterator@1.0.0: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} dependencies: internal-slot: 1.0.5 - /stream-buffers/0.2.6: + /stream-buffers@0.2.6: resolution: {integrity: sha512-ZRpmWyuCdg0TtNKk8bEqvm13oQvXMmzXDsfD4cBgcx5LouborvU5pm3JMkdTP3HcszyUI08AM1dHMXA5r2g6Sg==} engines: {node: '>= 0.3.0'} dev: true - /stream-transform/2.1.3: + /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: mixme: 0.5.4 dev: true - /string-hash/1.1.3: + /string-hash@1.1.3: resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} dev: false - /string-width/4.2.3: + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} dependencies: @@ -8608,7 +9138,7 @@ packages: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - /string-width/5.1.2: + /string-width@5.1.2: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} dependencies: @@ -8616,7 +9146,7 @@ packages: emoji-regex: 9.2.2 strip-ansi: 7.0.1 - /string.prototype.matchall/4.0.8: + /string.prototype.matchall@4.0.8: resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} dependencies: call-bind: 1.0.2 @@ -8629,57 +9159,57 @@ packages: side-channel: 1.0.4 dev: true - /string.prototype.trimend/1.0.6: + /string.prototype.trimend@1.0.6: resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} dependencies: call-bind: 1.0.2 define-properties: 1.2.0 es-abstract: 1.20.4 - /string.prototype.trimstart/1.0.6: + /string.prototype.trimstart@1.0.6: resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} dependencies: call-bind: 1.0.2 define-properties: 1.2.0 es-abstract: 1.20.4 - /strip-ansi/6.0.1: + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 - /strip-ansi/7.0.1: + /strip-ansi@7.0.1: resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 - /strip-bom/3.0.0: + /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - /strip-indent/3.0.0: + /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} dependencies: min-indent: 1.0.1 dev: true - /strip-json-comments/3.1.1: + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - /strip-literal/1.0.0: + /strip-literal@1.0.0: resolution: {integrity: sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 - /style-inject/0.3.0: + /style-inject@0.3.0: resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} dev: false - /styled-components/5.3.6_pumtretovylab5lwhztzjp2kuy: + /styled-components@5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0): resolution: {integrity: sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==} engines: {node: '>=10'} requiresBuild: true @@ -8689,21 +9219,21 @@ packages: react-is: '>= 16.8.0' dependencies: '@babel/helper-module-imports': 7.18.6 - '@babel/traverse': 7.20.1_supports-color@5.5.0 + '@babel/traverse': 7.20.1(supports-color@5.5.0) '@emotion/is-prop-valid': 1.2.0 '@emotion/stylis': 0.8.5 '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.0.7_styled-components@5.3.6 + babel-plugin-styled-components: 2.0.7(styled-components@5.3.6) css-to-react-native: 3.0.0 hoist-non-react-statics: 3.3.2 react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 + react-dom: 18.2.0(react@18.2.0) react-is: 17.0.2 shallowequal: 1.1.0 supports-color: 5.5.0 dev: true - /stylehacks/5.1.1_postcss@8.4.20: + /stylehacks@5.1.1(postcss@8.4.20): resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: @@ -8714,23 +9244,23 @@ packages: postcss-selector-parser: 6.0.10 dev: false - /supports-color/5.5.0: + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} dependencies: has-flag: 3.0.0 - /supports-color/7.2.0: + /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - /supports-preserve-symlinks-flag/1.0.0: + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /svgo/2.8.0: + /svgo@2.8.0: resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} engines: {node: '>=10.13.0'} hasBin: true @@ -8744,72 +9274,72 @@ packages: stable: 0.1.8 dev: false - /symbol-tree/3.2.4: + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - /synckit/0.8.4: + /synckit@0.8.4: resolution: {integrity: sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==} engines: {node: ^14.18.0 || >=16.0.0} dependencies: '@pkgr/utils': 2.3.1 tslib: 2.5.0 - /tapable/2.2.1: + /tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - /term-size/2.2.1: + /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} dev: true - /term-size/3.0.2: + /term-size@3.0.2: resolution: {integrity: sha512-YfE8KwjrumviCxmeOS1r1hAwqUcd/AnhrG/Pol/Gry91EyUCS+jQH0qFUZOUkpGQ5rXsKMK6S6kjne53ytYS/w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - /text-table/0.2.0: + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - /tiny-glob/0.2.9: + /tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} dependencies: globalyzer: 0.1.0 globrex: 0.1.2 - /tinybench/2.3.1: + /tinybench@2.3.1: resolution: {integrity: sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==} - /tinypool/0.4.0: + /tinypool@0.4.0: resolution: {integrity: sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA==} engines: {node: '>=14.0.0'} - /tinyspy/1.0.2: + /tinyspy@1.0.2: resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==} engines: {node: '>=14.0.0'} - /tmp/0.0.33: + /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} dependencies: os-tmpdir: 1.0.2 dev: true - /to-fast-properties/2.0.0: + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - /to-regex-range/5.0.1: + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 - /totalist/3.0.0: + /totalist@3.0.0: resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} engines: {node: '>=6'} dev: true - /tough-cookie/4.1.2: + /tough-cookie@4.1.2: resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} engines: {node: '>=6'} dependencies: @@ -8818,38 +9348,38 @@ packages: universalify: 0.2.0 url-parse: 1.5.10 - /tr46/0.0.3: + /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: true - /tr46/3.0.0: + /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} dependencies: punycode: 2.3.0 - /tr46/4.1.1: + /tr46@4.1.1: resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} engines: {node: '>=14'} dependencies: punycode: 2.3.0 - /trim-newlines/3.0.1: + /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} dev: true - /ts-clone-node/1.0.0_typescript@5.0.2: + /ts-clone-node@1.0.0(typescript@5.0.2): resolution: {integrity: sha512-/cDYbr2HAXxFNeTT41c/xs/2bhLJjqnYheHsmA3AoHSt+n4JA4t0FL9Lk5O8kWnJ6jeB3kPcUoXIFtwERNzv6Q==} engines: {node: '>=14.9.0'} peerDependencies: typescript: '*' dependencies: - compatfactory: 1.0.1_typescript@5.0.2 + compatfactory: 1.0.1(typescript@5.0.2) typescript: 5.0.2 dev: false - /tsconfig-paths/3.14.1: + /tsconfig-paths@3.14.1: resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} dependencies: '@types/json5': 0.0.29 @@ -8857,13 +9387,13 @@ packages: minimist: 1.2.7 strip-bom: 3.0.0 - /tslib/1.14.1: + /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - /tslib/2.5.0: + /tslib@2.5.0: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - /tsutils/3.21.0_typescript@5.0.2: + /tsutils@3.21.0(typescript@5.0.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: @@ -8872,7 +9402,7 @@ packages: tslib: 1.14.1 typescript: 5.0.2 - /tsx/3.11.0: + /tsx@3.11.0: resolution: {integrity: sha512-q+q4xxu41+AafVwvAGqtNJ1ekPFd33ZhTMXvgIpHMqv/W89efwDRE9IyjhEAZm5iTHsshKaf1BYWSk789BrNCA==} hasBin: true dependencies: @@ -8883,7 +9413,7 @@ packages: fsevents: 2.3.2 dev: true - /tty-table/4.1.6: + /tty-table@4.1.6: resolution: {integrity: sha512-kRj5CBzOrakV4VRRY5kUWbNYvo/FpOsz65DzI5op9P+cHov3+IqPbo1JE1ZnQGkHdZgNFDsrEjrfqqy/Ply9fw==} engines: {node: '>=8.0.0'} hasBin: true @@ -8897,58 +9427,58 @@ packages: yargs: 17.6.2 dev: true - /type-check/0.3.2: + /type-check@0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.1.2 - /type-check/0.4.0: + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 - /type-detect/4.0.8: + /type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - /type-fest/0.13.1: + /type-fest@0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'} dev: true - /type-fest/0.20.2: + /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - /type-fest/0.6.0: + /type-fest@0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} engines: {node: '>=8'} dev: true - /type-fest/0.8.1: + /type-fest@0.8.1: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} dev: true - /typescript/5.0.2: + /typescript@5.0.2: resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==} engines: {node: '>=12.20'} hasBin: true - /ua-parser-js/1.0.32: + /ua-parser-js@1.0.32: resolution: {integrity: sha512-dXVsz3M4j+5tTiovFVyVqssXBu5HM47//YSOeZ9fQkdDKkfzv2v3PP1jmH6FUyPW+yCSn7aBVK1fGGKNhowdDA==} dev: false - /uberproto/1.2.0: + /uberproto@1.2.0: resolution: {integrity: sha512-pGtPAQmLwh+R9w81WVHzui1FfedpQWQpiaIIfPCwhtsBez4q6DYbJFfyXPVHPUTNFnedAvNEnkoFiLuhXIR94w==} dev: true - /ufo/1.1.1: + /ufo@1.1.1: resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} - /unbox-primitive/1.0.2: + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: call-bind: 1.0.2 @@ -8956,12 +9486,12 @@ packages: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - /unicode-canonical-property-names-ecmascript/2.0.0: + /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} dev: true - /unicode-match-property-ecmascript/2.0.0: + /unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} dependencies: @@ -8969,31 +9499,31 @@ packages: unicode-property-aliases-ecmascript: 2.1.0 dev: true - /unicode-match-property-value-ecmascript/2.0.0: + /unicode-match-property-value-ecmascript@2.0.0: resolution: {integrity: sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==} engines: {node: '>=4'} dev: true - /unicode-property-aliases-ecmascript/2.1.0: + /unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} dev: true - /universalify/0.1.2: + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} dev: true - /universalify/0.2.0: + /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} - /universalify/2.0.0: + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} dev: true - /update-browserslist-db/1.0.10_browserslist@4.21.4: + /update-browserslist-db@1.0.10(browserslist@4.21.4): resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} hasBin: true peerDependencies: @@ -9003,29 +9533,29 @@ packages: escalade: 3.1.1 picocolors: 1.0.0 - /uri-js/4.4.1: + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.0 - /url-parse/1.5.10: + /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} dependencies: querystringify: 2.2.0 requires-port: 1.0.0 - /util-deprecate/1.0.2: + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false - /validate-npm-package-license/3.0.4: + /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: spdx-correct: 3.1.1 spdx-expression-parse: 3.0.1 dev: true - /vite-node/0.29.7_@types+node@18.15.5: + /vite-node@0.29.7(@types/node@18.15.5): resolution: {integrity: sha512-PakCZLvz37yFfUPWBnLa1OYHPCGm5v4pmRrTcFN4V/N/T3I6tyP3z07S//9w+DdeL7vVd0VSeyMZuAh+449ZWw==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9035,7 +9565,27 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.2.1_@types+node@18.15.5 + vite: 4.2.1(@types/node@18.15.5) + transitivePeerDependencies: + - '@types/node' + - less + - sass + - stylus + - sugarss + - supports-color + - terser + + /vite-node@0.29.8(@types/node@18.15.5): + resolution: {integrity: sha512-b6OtCXfk65L6SElVM20q5G546yu10/kNrhg08afEoWlFRJXFq9/6glsvSVY+aI6YeC1tu2TtAqI2jHEQmOmsFw==} + engines: {node: '>=v14.16.0'} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + mlly: 1.2.0 + pathe: 1.1.0 + picocolors: 1.0.0 + vite: 4.2.1(@types/node@18.15.5) transitivePeerDependencies: - '@types/node' - less @@ -9044,8 +9594,9 @@ packages: - sugarss - supports-color - terser + dev: true - /vite-plugin-fonts/0.7.0_vite@4.2.1: + /vite-plugin-fonts@0.7.0(vite@4.2.1): resolution: {integrity: sha512-fisKirkQrA2RFwcyI96SENLu1FyRYNIiC/l5DGdD8oV3OsAWGrYKs0e7/VZF6l0rm0QiYA2sOVTzYfrLAzP9cw==} peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 @@ -9053,7 +9604,7 @@ packages: fast-glob: 3.2.12 vite: 4.2.1 - /vite-plugin-mpa/1.1.4: + /vite-plugin-mpa@1.1.4: resolution: {integrity: sha512-sLXMOdMl8t9B9/sxXXZ9CLt8QudhGSSKCX+bZ/ePaO7kp4SdoA5d6CV+EnCyNuQCenAbXKJzk3nM8Do0RgmSpA==} dependencies: connect-history-api-fallback: 1.6.0 @@ -9061,7 +9612,7 @@ packages: yargs: 16.2.0 dev: true - /vite/4.2.1: + /vite@4.2.1: resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -9093,7 +9644,7 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vite/4.2.1_@types+node@18.15.5: + /vite@4.2.1(@types/node@18.15.5): resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -9126,7 +9677,7 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vitest/0.29.7_@vitest+ui@0.29.7: + /vitest@0.29.7(@vitest/ui@0.29.7): resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9176,8 +9727,8 @@ packages: tinybench: 2.3.1 tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.2.1_@types+node@18.15.5 - vite-node: 0.29.7_@types+node@18.15.5 + vite: 4.2.1(@types/node@18.15.5) + vite-node: 0.29.7(@types/node@18.15.5) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9188,7 +9739,7 @@ packages: - terser dev: true - /vitest/0.29.7_bi73zdcwqjrbwiah6tn5sspwie: + /vitest@0.29.7(jsdom@21.1.1): resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9222,14 +9773,12 @@ packages: '@vitest/expect': 0.29.7 '@vitest/runner': 0.29.7 '@vitest/spy': 0.29.7 - '@vitest/ui': 0.29.7 '@vitest/utils': 0.29.7 - acorn: 8.8.1 + acorn: 8.8.2 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 - happy-dom: 8.9.0 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 @@ -9240,8 +9789,8 @@ packages: tinybench: 2.3.1 tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.2.1_@types+node@18.15.5 - vite-node: 0.29.7_@types+node@18.15.5 + vite: 4.2.1(@types/node@18.15.5) + vite-node: 0.29.7(@types/node@18.15.5) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9250,10 +9799,10 @@ packages: - sugarss - supports-color - terser - dev: true + dev: false - /vitest/0.29.7_jsdom@21.1.1: - resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} + /vitest@0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1): + resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==} engines: {node: '>=v14.16.0'} hasBin: true peerDependencies: @@ -9262,6 +9811,7 @@ packages: '@vitest/ui': '*' happy-dom: '*' jsdom: '*' + playwright: '*' safaridriver: '*' webdriverio: '*' peerDependenciesMeta: @@ -9275,6 +9825,8 @@ packages: optional: true jsdom: optional: true + playwright: + optional: true safaridriver: optional: true webdriverio: @@ -9283,15 +9835,17 @@ packages: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 '@types/node': 18.15.5 - '@vitest/expect': 0.29.7 - '@vitest/runner': 0.29.7 - '@vitest/spy': 0.29.7 - '@vitest/utils': 0.29.7 + '@vitest/expect': 0.29.8 + '@vitest/runner': 0.29.8 + '@vitest/spy': 0.29.8 + '@vitest/ui': 0.29.8 + '@vitest/utils': 0.29.8 acorn: 8.8.2 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 + happy-dom: 8.9.0 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 @@ -9302,8 +9856,8 @@ packages: tinybench: 2.3.1 tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.2.1_@types+node@18.15.5 - vite-node: 0.29.7_@types+node@18.15.5 + vite: 4.2.1(@types/node@18.15.5) + vite-node: 0.29.8(@types/node@18.15.5) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9312,9 +9866,9 @@ packages: - sugarss - supports-color - terser - dev: false + dev: true - /vscode-json-languageservice/4.2.1: + /vscode-json-languageservice@4.2.1: resolution: {integrity: sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==} dependencies: jsonc-parser: 3.2.0 @@ -9324,74 +9878,74 @@ packages: vscode-uri: 3.0.6 dev: false - /vscode-languageserver-textdocument/1.0.7: + /vscode-languageserver-textdocument@1.0.7: resolution: {integrity: sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==} dev: false - /vscode-languageserver-types/3.17.2: + /vscode-languageserver-types@3.17.2: resolution: {integrity: sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==} dev: false - /vscode-nls/5.2.0: + /vscode-nls@5.2.0: resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} dev: false - /vscode-uri/3.0.6: + /vscode-uri@3.0.6: resolution: {integrity: sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==} dev: false - /w3c-xmlserializer/4.0.0: + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} dependencies: xml-name-validator: 4.0.0 - /wcwidth/1.0.1: + /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: defaults: 1.0.4 dev: true - /webidl-conversions/3.0.1: + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: true - /webidl-conversions/7.0.0: + /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - /whatwg-encoding/2.0.0: + /whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} dependencies: iconv-lite: 0.6.3 - /whatwg-mimetype/3.0.0: + /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} - /whatwg-url/11.0.0: + /whatwg-url@11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} engines: {node: '>=12'} dependencies: tr46: 3.0.0 webidl-conversions: 7.0.0 - /whatwg-url/12.0.1: + /whatwg-url@12.0.1: resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==} engines: {node: '>=14'} dependencies: tr46: 4.1.1 webidl-conversions: 7.0.0 - /whatwg-url/5.0.0: + /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 dev: true - /which-boxed-primitive/1.0.2: + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: is-bigint: 1.0.4 @@ -9400,7 +9954,7 @@ packages: is-string: 1.0.7 is-symbol: 1.0.4 - /which-collection/1.0.1: + /which-collection@1.0.1: resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} dependencies: is-map: 2.0.2 @@ -9408,11 +9962,11 @@ packages: is-weakmap: 2.0.1 is-weakset: 2.0.2 - /which-module/2.0.0: + /which-module@2.0.0: resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} dev: true - /which-pm/2.0.0: + /which-pm@2.0.0: resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} engines: {node: '>=8.15'} dependencies: @@ -9420,7 +9974,7 @@ packages: path-exists: 4.0.0 dev: true - /which-typed-array/1.1.9: + /which-typed-array@1.1.9: resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} engines: {node: '>= 0.4'} dependencies: @@ -9431,21 +9985,21 @@ packages: has-tostringtag: 1.0.0 is-typed-array: 1.1.10 - /which/1.3.1: + /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true dependencies: isexe: 2.0.0 dev: true - /which/2.0.2: + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true dependencies: isexe: 2.0.0 - /why-is-node-running/2.2.2: + /why-is-node-running@2.2.2: resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} engines: {node: '>=8'} hasBin: true @@ -9453,11 +10007,11 @@ packages: siginfo: 2.0.0 stackback: 0.0.2 - /word-wrap/1.2.3: + /word-wrap@1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} - /wrap-ansi/6.2.0: + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} dependencies: @@ -9466,7 +10020,7 @@ packages: strip-ansi: 6.0.1 dev: true - /wrap-ansi/7.0.0: + /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} dependencies: @@ -9474,7 +10028,7 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 - /wrap-ansi/8.0.1: + /wrap-ansi@8.0.1: resolution: {integrity: sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==} engines: {node: '>=12'} dependencies: @@ -9482,10 +10036,10 @@ packages: string-width: 5.1.2 strip-ansi: 7.0.1 - /wrappy/1.0.2: + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws/8.11.0: + /ws@8.11.0: resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} engines: {node: '>=10.0.0'} peerDependencies: @@ -9497,7 +10051,7 @@ packages: utf-8-validate: optional: true - /ws/8.13.0: + /ws@8.13.0: resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} engines: {node: '>=10.0.0'} peerDependencies: @@ -9509,38 +10063,38 @@ packages: utf-8-validate: optional: true - /xml-name-validator/4.0.0: + /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} - /xmlchars/2.2.0: + /xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - /y18n/4.0.3: + /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} dev: true - /y18n/5.0.8: + /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - /yallist/2.1.2: + /yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} dev: true - /yallist/3.1.1: + /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} dev: true - /yallist/4.0.0: + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - /yaml/1.10.2: + /yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} dev: false - /yargs-parser/18.1.3: + /yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} dependencies: @@ -9548,16 +10102,16 @@ packages: decamelize: 1.2.0 dev: true - /yargs-parser/20.2.9: + /yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} - /yargs-parser/21.1.1: + /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} dev: true - /yargs/15.4.1: + /yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} dependencies: @@ -9574,7 +10128,7 @@ packages: yargs-parser: 18.1.3 dev: true - /yargs/16.2.0: + /yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} dependencies: @@ -9586,7 +10140,7 @@ packages: y18n: 5.0.8 yargs-parser: 20.2.9 - /yargs/17.6.2: + /yargs@17.6.2: resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} engines: {node: '>=12'} dependencies: @@ -9599,10 +10153,10 @@ packages: yargs-parser: 21.1.1 dev: true - /yocto-queue/0.1.0: + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - /yocto-queue/1.0.0: + /yocto-queue@1.0.0: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} From 9665534806f7ff36cc5cda26583778e949ebe311 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 31 Mar 2023 15:15:06 -0700 Subject: [PATCH 17/46] WIP --- packages/universal/reactive/index.ts | 1 + packages/universal/reactive/src/utils.ts | 10 +- packages/universal/resource/index.ts | 5 +- packages/universal/resource/package.json | 1 + .../universal/resource/src/resource-list.ts | 19 +- packages/universal/resource/src/resource.ts | 201 ++++++-------- packages/universal/resource/src/types.ts | 29 ++ .../resource/tests/resource-list.spec.ts | 32 +-- .../universal/resource/tests/resource.spec.ts | 135 +++++++++- .../universal/tests/resource.spec.ts | 250 +----------------- 10 files changed, 287 insertions(+), 396 deletions(-) create mode 100644 packages/universal/resource/src/types.ts diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 4a0cb838..5da68aea 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -12,4 +12,5 @@ export { isReactive, isTaggedReactive, read, + type ReadValue, } from "./src/utils.js"; diff --git a/packages/universal/reactive/src/utils.ts b/packages/universal/reactive/src/utils.ts index 429dc538..636c4b36 100644 --- a/packages/universal/reactive/src/utils.ts +++ b/packages/universal/reactive/src/utils.ts @@ -34,15 +34,17 @@ export function isTaggedReactive( return is(value) && value[TAG].type === tag && hasRead(value); } +export type ReadValue = T extends Reactive ? R : T; + export function read( this: void, - value: T | Reactive, + value: T, caller = callerStack() -): T { +): ReadValue { if (is(value) && hasRead(value)) { - return value.read(caller); + return value.read(caller) as ReadValue; } else { - return value; + return value as ReadValue; } } diff --git a/packages/universal/resource/index.ts b/packages/universal/resource/index.ts index 760576d1..9a0d638f 100644 --- a/packages/universal/resource/index.ts +++ b/packages/universal/resource/index.ts @@ -1,3 +1,4 @@ -export type { ResourceBlueprint, UseResource } from "./src/resource.js"; -export { Resource, ResourceRun, use } from "./src/resource.js"; +export type { ResourceBlueprint } from "./src/resource.js"; +export { lifetime, Resource, ResourceRun, use } from "./src/resource.js"; export { FormulaList, ResourceList } from "./src/resource-list.js"; +export type { UseMethod, UseResource } from "./src/types.js"; diff --git a/packages/universal/resource/package.json b/packages/universal/resource/package.json index d66bea69..d74e2bef 100644 --- a/packages/universal/resource/package.json +++ b/packages/universal/resource/package.json @@ -1,5 +1,6 @@ { "name": "@starbeam/resource", + "main": "index.ts", "types": "index.ts", "publishConfig": { "exports": { diff --git a/packages/universal/resource/src/resource-list.ts b/packages/universal/resource/src/resource-list.ts index 9bece506..3ff09b19 100644 --- a/packages/universal/resource/src/resource-list.ts +++ b/packages/universal/resource/src/resource-list.ts @@ -1,8 +1,8 @@ import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { CachedFormula, Formula } from "@starbeam/reactive"; +import { CachedFormula, Formula, type ReadValue } from "@starbeam/reactive"; import { LIFETIME } from "@starbeam/runtime"; -import { Resource, type ResourceBlueprint } from "./resource.js"; +import { Resource, type ResourceBlueprint, use } from "./resource.js"; export function ResourceList( list: Iterable, @@ -13,11 +13,11 @@ export function ResourceList( key: (item: T) => unknown; map: (item: T) => ResourceBlueprint; } -): ResourceBlueprint[]> { +): ResourceBlueprint>[]> { const resources = new ResourceMap(); return Resource((_, { lifetime }) => { - const result: Resource[] = []; + const result: Resource>[] = []; const remaining = new Set(); for (const item of list) { const k = key(item); @@ -37,12 +37,15 @@ export function ResourceList( }); } -type InternalMap = Map; lifetime: object }>; +type InternalMap = Map< + unknown, + { resource: Resource>; lifetime: object } +>; class ResourceMap { readonly #map: InternalMap = new Map(); - get(key: unknown): Resource | undefined { + get(key: unknown): Resource> | undefined { return this.#map.get(key)?.resource; } @@ -50,10 +53,10 @@ class ResourceMap { key: unknown, resource: ResourceBlueprint, parentLifetime: object - ): Resource { + ): Resource> { const lifetime = {}; LIFETIME.link(parentLifetime, lifetime); - const newResource = resource.create({ lifetime }); + const newResource = use(resource, { lifetime }); this.#map.set(key, { resource: newResource, lifetime }); return newResource; } diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index 338f9955..400efe7a 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -1,14 +1,20 @@ import { DisplayStruct } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; -import { CachedFormula, type FormulaFn, isFormulaFn } from "@starbeam/reactive"; +import { + CachedFormula, + type FormulaFn, + isFormulaFn, + read, + type ReadValue, +} from "@starbeam/reactive"; import { LIFETIME, TAG } from "@starbeam/runtime"; -export type UseResource = - | ResourceBlueprint - | (() => ResourceBlueprint) - | Resource; - -let id = 0; +import type { + ResourceCleanup, + ResourceConstructor, + UseMethod, + UseResource, +} from "./types.js"; /** * `ResourceRun` is passed in to the user-specified `ResourceConstructor` @@ -18,10 +24,12 @@ let id = 0; */ export class ResourceRun { readonly #state: ResourceState; - readonly id = id++; - constructor(state: ResourceState) { - this.#state = state; + constructor(state: ResourceOptions) { + this.#state = { + metadata: undefined, + ...state, + } as ResourceState; } on = { @@ -50,86 +58,37 @@ export class ResourceRun { resource: UseResource, metadata?: unknown ): FormulaFn => { - return use(resource, { metadata, root: this.#state.root, lifetime: this }); + return use(resource, { metadata, lifetime: this }); }) as UseMethod; } -type UseMethod = ((resource: UseResource) => FormulaFn) & - ((resource: UseResource, metadata: M) => FormulaFn); - -export type Resource = FormulaFn; - -function useResource( - resource: Resource, - state: ResourceState -): Resource { - LIFETIME.link(state.lifetime, resource, { root: state.root }); - return resource; -} - -function useResourceConstructor( - resource: ResourceConstructor, - state: ResourceState -): Resource { - let last: ResourceRun | undefined; - const formula = CachedFormula(() => { - const next = new ResourceRun(state); - - LIFETIME.link(state.lifetime, next, { root: state.root }); - const instance = resource(next, { - metadata: state.metadata, - lifetime: state.lifetime, - }); - - // Finalize the previous run after running the new one to give the new one a - // chance to adopt resources from the previous run. - if (last !== undefined) LIFETIME.finalize(last); - last = next; - - return instance; - }); - - if (import.meta.env.DEV) { - Object.defineProperty(formula, Symbol.for("nodejs.util.inspect.custom"), { - configurable: true, - value: () => { - return DisplayStruct("Resource", { - tag: formula[TAG], - }); - }, - }); - } - - return formula; -} - /** * A blueprint is a reactive object that evaluates to the current * resource run for a given resource constructor. */ export function use( resource: UseResource, - state: ResourceState -): Resource { + state: ResourceOptions +): Resource> { if (isFormulaFn(resource)) { - return useResource(resource, state); + return resource as Resource>; } else if (typeof resource === "function") { - return resource().use(state); + return Resource(resource).use(state); } else { - return resource.use(state); + return resource.use(state) as Resource>; } } +type ResourceOptions = M extends void + ? Omit, "metadata"> + : ResourceState; + interface ResourceState { /** * A resource's metadata persists across runs of the resource. */ readonly metadata: M; - /** - * A resource's root is the root of the resource tree. It is used to adopt - * resources across runs. - */ - readonly root: object; + /** * A resource's lifetime is the direct parent of the resource. The direct * parent is contained inside the root. @@ -138,64 +97,64 @@ interface ResourceState { } export interface ResourceBlueprint { - create: (( - this: ResourceBlueprint, - options: { - lifetime: object; - metadata?: undefined; - } - ) => Resource) & - ((options: { lifetime: object; metadata: M }) => Resource); - use: (options: { - lifetime: object; - metadata: M; - root: object; - }) => Resource; + use: (options: ResourceOptions) => Resource; } +export type Resource = FormulaFn; + export function Resource( resource: ResourceConstructor, _description?: string | Description -): ResourceBlueprint { +): ResourceBlueprint, M> { return { - create: ({ lifetime, metadata }) => { - return useResourceConstructor(resource, { - lifetime, - root: lifetime, - metadata: metadata as M, - }); - }, - use: ({ - lifetime, - metadata, - root, - }: { - lifetime: object; - metadata: M; - root: object; - }) => { - return useResourceConstructor(resource, { - lifetime, - metadata, - root, - }); + use: (options: ResourceOptions) => { + return useResourceConstructor(resource, options); }, }; } -/** - * A resource constructor is a user-defined function that runs for each resource - * run. - */ -type ResourceConstructor = ( - run: ResourceRun, - /** - * The `resource` parameter provides information about the entire resource - * that persists across runs. It is useful when reusing state across runs. The - * `lifetime` property makes it possible to link state to the entire lifetime - * of the resource, which ensures that it it will get cleaned up, at the - * latest, when the resource itself is finalized. - */ - resource: { metadata: M; lifetime: object } -) => T; -type ResourceCleanup = (metadata: M) => void; +const RESOURCE_LIFETIMES = new WeakMap, object>(); + +export function lifetime(resource: Resource): object { + return RESOURCE_LIFETIMES.get(resource) as object; +} + +function useResourceConstructor( + resource: ResourceConstructor, + options: ResourceOptions +): Resource> { + let last: ResourceRun | undefined; + const formula = CachedFormula(() => { + const next = new ResourceRun(options); + + LIFETIME.link(options.lifetime, next); + const instance = resource(next, { + metadata: undefined, + ...options, + } as ResourceState); + + // Finalize the previous run after running the new one to give the new one a + // chance to adopt resources from the previous run. + if (last !== undefined) LIFETIME.finalize(last); + last = next; + + return instance; + }); + + if (import.meta.env.DEV) { + Object.defineProperty(formula, Symbol.for("nodejs.util.inspect.custom"), { + configurable: true, + value: () => { + return DisplayStruct("Resource", { + tag: formula[TAG], + }); + }, + }); + } + + const instance = CachedFormula(() => read(formula.current) as ReadValue); + + RESOURCE_LIFETIMES.set(instance, options.lifetime); + + return instance; +} diff --git a/packages/universal/resource/src/types.ts b/packages/universal/resource/src/types.ts new file mode 100644 index 00000000..0e6d2848 --- /dev/null +++ b/packages/universal/resource/src/types.ts @@ -0,0 +1,29 @@ +import type { FormulaFn } from "@starbeam/reactive"; + +import type { Resource, ResourceBlueprint, ResourceRun } from "./resource.js"; + +export type UseResource = + | ResourceBlueprint + | ResourceConstructor + | Resource; + +export type UseMethod = ((resource: UseResource) => FormulaFn) & + ((resource: UseResource, metadata: M) => FormulaFn); + +/** + * A resource constructor is a user-defined function that runs for each resource + * run. + */ +export type ResourceConstructor = ( + run: ResourceRun, + /** + * The `resource` parameter provides information about the entire resource + * that persists across runs. It is useful when reusing state across runs. The + * `lifetime` property makes it possible to link state to the entire lifetime + * of the resource, which ensures that it it will get cleaned up, at the + * latest, when the resource itself is finalized. + */ + resource: { metadata: M; lifetime: object } +) => T; + +export type ResourceCleanup = (metadata: M) => void; diff --git a/packages/universal/resource/tests/resource-list.spec.ts b/packages/universal/resource/tests/resource-list.spec.ts index b7201972..8b4e3070 100644 --- a/packages/universal/resource/tests/resource-list.spec.ts +++ b/packages/universal/resource/tests/resource-list.spec.ts @@ -1,10 +1,11 @@ import { DisplayStruct } from "@starbeam/debug"; import { reactive } from "@starbeam/js"; -import { CachedFormula, Cell, type FormulaFn } from "@starbeam/reactive"; +import { CachedFormula, Cell } from "@starbeam/reactive"; import { Resource, type ResourceBlueprint, ResourceList, + use, } from "@starbeam/resource"; import { LIFETIME } from "@starbeam/runtime"; import { describe, expect, test } from "@starbeam-workspace/test-utils"; @@ -44,7 +45,7 @@ class Subscription { } } -describe("v3::ResourceList", () => { +describe("ResourceList", () => { test("smoke test", () => { const list: Item[] = reactive.array([ { id: 1, name: "Tom", location: "NYC" }, @@ -72,10 +73,13 @@ describe("v3::ResourceList", () => { }; const lifetime = { lifetime: "root" }; - const mapped = ResourceList(list, { - key: (item) => item.id, - map, - }).create({ lifetime }); + const mapped = use( + ResourceList(list, { + key: (item) => item.id, + map, + }), + { lifetime } + ); expect(mapped.current.map((r) => r.current)).toEqual([ { active: true, desc: "Tom (NYC)" }, @@ -107,12 +111,10 @@ describe("v3::ResourceList", () => { const map = ( item: Item - ): ResourceBlueprint< - FormulaFn<{ - card: string; - subscription: Subscription; - }> - > => + ): ResourceBlueprint<{ + card: string; + subscription: Subscription; + }> => Resource(({ on }) => { const subscription = new Subscription(item.name); subscription.connect(); @@ -135,10 +137,10 @@ describe("v3::ResourceList", () => { map, }); - const resources = linkables.create({ lifetime }); + const resources = use(linkables, { lifetime }); function current(): { card: string; subscription: Subscription }[] { - return resources.current.map((r) => r.current.current); + return resources.current.map((r) => r.current); } expect(current()).toEqual([ @@ -190,7 +192,7 @@ describe("v3::ResourceList", () => { { id: 1, name: "Tom", location: "NYC" }, ]); - currentResources = resources.current.map((r) => r.current.current); + currentResources = resources.current.map((r) => r.current); expect(currentResources[0]?.subscription).toBe(chirag); expect(currentResources[1]?.subscription).toBe(tom); diff --git a/packages/universal/resource/tests/resource.spec.ts b/packages/universal/resource/tests/resource.spec.ts index 68d097eb..2ae22df7 100644 --- a/packages/universal/resource/tests/resource.spec.ts +++ b/packages/universal/resource/tests/resource.spec.ts @@ -1,9 +1,9 @@ -import { Cell, Marker } from "@starbeam/reactive"; -import { Resource, type ResourceBlueprint } from "@starbeam/resource"; +import { CachedFormula, Cell, Marker } from "@starbeam/reactive"; +import { Resource, type ResourceBlueprint, use } from "@starbeam/resource"; import { LIFETIME } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; -describe("v3::resources", () => { +describe("resources", () => { test("the basics", () => { const testResource = new TestResource(); const resource = testResource.instance; @@ -43,6 +43,78 @@ describe("v3::resources", () => { }); }); + test("if a resource constructor returns a reactive value, it is assimilated", () => { + const initial = Cell(0); + const plus = Cell(0); + const counts = { init: 0, finalized: 0 }; + const Test = Resource(({ on }) => { + counts.init++; + const cell = Cell(initial.current); + + on.cleanup(() => { + counts.finalized++; + }); + + return CachedFormula(() => cell.current + plus.current); + }); + + const lifetime = {}; + const test = use(Test, { lifetime }); + + expect(test.current).toBe(0); + expect(counts).toEqual({ init: 1, finalized: 0 }); + + plus.current++; + expect(test.current).toBe(1); + expect(counts).toEqual({ init: 1, finalized: 0 }); + + initial.current++; + expect(test.current).toBe(2); + expect(counts).toEqual({ init: 2, finalized: 1 }); + }); + + test("a counter that persists across cleanups", () => { + const counts = { init: 0, finalized: 0 }; + const invalidate = Marker(); + const Counter = Resource( + ({ on }, { metadata: count }: { metadata: Cell }) => { + invalidate.read(); + counts.init++; + + on.cleanup(() => { + counts.finalized++; + }); + + return { + get count() { + return count.current; + }, + increment() { + count.current++; + }, + }; + } + ); + + const lifetime = {}; + const counter = use(Counter, { lifetime, metadata: Cell(0) }); + + expect(counter.current.count).toBe(0); + expect(counts).toEqual({ init: 1, finalized: 0 }); + + counter.current.increment(); + expect(counter.current.count).toBe(1); + expect(counts).toEqual({ init: 1, finalized: 0 }); + + invalidate.mark(); + expect(counter.current.count).toBe(1); + expect(counts).toEqual({ init: 2, finalized: 1 }); + + counter.current.increment(); + expect(counter.current.count).toBe(2); + expect(counts).toEqual({ init: 2, finalized: 1 }); + }); + test("child resources", () => { const name = Cell("default"); let connectedCount = 0; @@ -83,7 +155,7 @@ describe("v3::resources", () => { }); const lifetime = {}; - const channel = Channel.create({ lifetime }); + const channel = use(Channel, { lifetime }); expect(channel.current.description).toBe( "default (connected: 1, messages: 0)" @@ -129,7 +201,7 @@ describe("v3::resources", () => { ); const lifetime = {}; - const parent = Parent.create({ + const parent = use(Parent, { lifetime, metadata: { initHere: 0, @@ -175,6 +247,57 @@ describe("v3::resources", () => { }, }); }); + + test("modifying a resource constructor's dependency after it was finalized doesn't cause it to run again", () => { + const counts = { init: 0, finalized: 0 }; + const invalidate = Marker(); + + const Counter = Resource( + ({ on }, { metadata: count }: { metadata: Cell }) => { + invalidate.read(); + counts.init++; + + on.cleanup(() => { + counts.finalized++; + }); + + return { + get count() { + return count.current; + }, + increment() { + count.current++; + }, + }; + } + ); + + const lifetime = {}; + const counter = use(Counter, { lifetime, metadata: Cell(0) }); + + expect(counter.current.count).toBe(0); + expect(counts).toEqual({ init: 1, finalized: 0 }); + + counter.current.increment(); + expect(counter.current.count).toBe(1); + expect(counts).toEqual({ init: 1, finalized: 0 }); + + invalidate.mark(); + expect(counter.current.count).toBe(1); + expect(counts).toEqual({ init: 2, finalized: 1 }); + + counter.current.increment(); + expect(counter.current.count).toBe(2); + expect(counts).toEqual({ init: 2, finalized: 1 }); + + LIFETIME.finalize(lifetime); + expect(counts).toEqual({ init: 2, finalized: 2 }); + + // modifying the dependency after the resource was finalized should not + // cause it to run again + invalidate.mark(); + expect(counts).toEqual({ init: 2, finalized: 2 }); + }); }); interface TestInstance { @@ -224,7 +347,7 @@ class TestResource { }; }); - this.#instance = this.#blueprint.create({ lifetime: this.#lifetime }); + this.#instance = use(this.#blueprint, { lifetime: this.#lifetime }); } get instance(): Resource { diff --git a/packages/universal/universal/tests/resource.spec.ts b/packages/universal/universal/tests/resource.spec.ts index c9a1a93d..09602fad 100644 --- a/packages/universal/universal/tests/resource.spec.ts +++ b/packages/universal/universal/tests/resource.spec.ts @@ -1,14 +1,5 @@ -import { - getLast, - getLastIndex, - isPresent, - isPresentArray, - withoutLast, -} from "@starbeam/core-utils"; -import type { Description } from "@starbeam/debug"; import { callerStack, - Desc, DisplayStruct, entryPointFn, entryPoints, @@ -20,13 +11,12 @@ import { LIFETIME, Resource, type ResourceBlueprint, + use, Wrap, } from "@starbeam/universal"; -import { exhaustive, verified } from "@starbeam/verify"; +import { exhaustive } from "@starbeam/verify"; import { describe, expect, test } from "vitest"; -import { scenario } from "./support/scenario.js"; - const INITIAL_ID = 0; class Socket { @@ -176,7 +166,7 @@ describe("use()", () => { const parent = {}; - const instance = outer.create(parent); + const instance = use(outer, { lifetime: parent }); expect(instance.current).toBe("active (run = 0, i = 0)"); expect(prevInner?.current).toBe(undefined); @@ -214,248 +204,28 @@ describe("use()", () => { ); }, "Outer"); - const outer = Outer.root(); + const lifetime = {}; + const outer = use(Outer, { lifetime }); - expect(outer.resource.current).toBe( + expect(outer.current).toBe( "outer: active (0), inner: active, formula-dep: 0" ); formulaDep.update((i) => i + INCREMENT); - expect(outer.resource.current).toBe( + expect(outer.current).toBe( "outer: active (0), inner: active, formula-dep: 1" ); expect(inner.current).toBe("inner: active"); outerDep.update((i) => i + INCREMENT); - expect(outer.resource.current).toBe( + expect(outer.current).toBe( "outer: active (1), inner: active, formula-dep: 1" ); }); }); -scenario("use(resource)", () => { - const { resource: inner } = TestResource("inner"); - - const outerDep = Counter("OuterDep"); - const formulaDep = Counter("FormulaDep"); - - return { - inner, - deps: { - run: outerDep, - counter: formulaDep, - }, - }; -}) - .test( - "the return value of use() is the same as the value of the resource passed to use()", - ({ inner: Inner }) => { - const { resource: outer, owner } = Resource(({ use }) => { - const inner = use(Inner); - expect(inner).toBe(Inner); - return inner; - }, "Outer").root(); - - expect(outer.current).toBe("inner: active"); - - // the inner resource is finalized regardless of how the outer resoruce is finalized. - return [ - () => { - LIFETIME.finalize(owner); - expect(outer.current).toBe("inner: finalized"); - }, - () => { - LIFETIME.finalize(outer); - expect(outer.current).toBe("inner: finalized"); - }, - ]; - } - ) - .test("a reused inner value is not finalized", ({ inner: Inner, deps }) => { - const { resource: outer, owner } = Resource(({ use }) => { - const run = deps.run.current; - - const inner = use(Inner); - expect(inner).toBe(Inner); - - return Formula( - () => `${inner.current} (run: ${run}, counter: ${deps.counter.current})` - ); - }, "Outer").root(); - - expect(outer.current).toBe("inner: active (run: 0, counter: 0)"); - - deps.counter.increment(); - expect(outer.current).toBe("inner: active (run: 0, counter: 1)"); - - deps.run.increment(); - expect(outer.current).toBe("inner: active (run: 1, counter: 1)"); - - deps.counter.increment(); - deps.run.increment(); - expect(outer.current).toBe("inner: active (run: 2, counter: 2)"); - - // the inner resource is finalized regardless of how the outer resoruce is finalized. - return [ - () => { - LIFETIME.finalize(owner); - expect(outer.current).toBe("inner: finalized (run: 2, counter: 2)"); - }, - () => { - LIFETIME.finalize(outer); - expect(outer.current).toBe("inner: finalized (run: 2, counter: 2)"); - }, - ]; - }) - .test( - "an inner value that wasn't reused is finalized", - ({ inner: Inner, deps }) => { - function OnTheFly(value: number): TestResourceState { - return TestResource(`on-the-fly-${value}`); - } - - const items = new Items(); - - const verifyInvariants = entryPointFn( - ({ finalized = false }: { finalized?: boolean } = {}) => { - if (!finalized && items.active) { - const { item, index } = items.active; - expect(item?.resource.current).toBe(`on-the-fly-${index}: active`); - } - - const inactive = finalized ? items.all : items.inactive; - - inactive.forEach((item, i) => { - expect(item.resource.current).toBe(`on-the-fly-${i}: finalized`); - }); - } - ); - - const { resource: outer, owner } = Resource(({ use }) => { - const run = deps.run.current; - - const inner = use(Inner); - expect(inner).toBe(Inner); - const dynamicResource = OnTheFly(run); - const usedDynamicResource = use(dynamicResource.resource); - items.push(dynamicResource); - - return Formula(() => ({ - inner: inner.current, - run, - counter: deps.counter.current, - dynamic: usedDynamicResource.current, - })); - }, "Outer").root(); - - expect(outer.current).toStrictEqual({ - inner: "inner: active", - run: 0, - counter: 0, - dynamic: "on-the-fly-0: active", - }); - - verifyInvariants(); - - deps.counter.increment(); - - expect(outer.current).toStrictEqual({ - inner: "inner: active", - run: 0, - counter: 1, - dynamic: "on-the-fly-0: active", - }); - - verifyInvariants(); - - deps.run.increment(); - - expect(outer.current).toStrictEqual({ - inner: "inner: active", - run: 1, - counter: 1, - dynamic: "on-the-fly-1: active", - }); - - verifyInvariants(); - - return [ - () => { - LIFETIME.finalize(owner); - expect(Inner.current).toBe("inner: finalized"); - expect(outer.current).toStrictEqual({ - inner: "inner: finalized", - run: 1, - counter: 1, - dynamic: "on-the-fly-1: finalized", - }); - verifyInvariants({ finalized: true }); - }, - () => { - const active = verified(items.active?.item?.resource, isPresent); - LIFETIME.finalize(Inner); - - expect(Inner.current).toBe("inner: finalized"); - verifyInvariants({ finalized: false }); - - LIFETIME.finalize(active); - expect(Inner.current).toBe("inner: finalized"); - expect(active.current).toBe("on-the-fly-1: finalized"); - - verifyInvariants({ finalized: true }); - }, - ]; - } - ); - -class Items { - readonly #items: T[] = []; - - get all(): T[] { - return this.#items; - } - - get inactive(): T[] { - return withoutLast(this.#items); - } - - get activeIndex(): number | undefined { - return getLastIndex(this.#items); - } - - get active(): { item: T | undefined; index: number } | undefined { - if (isPresentArray(this.#items)) { - const item = getLast(this.#items); - const index = getLastIndex(this.#items); - - return { item, index }; - } - } - - push(item: T): void { - this.#items.push(item); - } -} - -function Counter( - description?: Description | string -): { increment: () => void } & Cell { - const desc = Desc("cell", description); - const cell = Cell(INITIAL_COUNT, { description: desc }); - - return Wrap( - cell, - { - increment() { - cell.update((i) => i + INCREMENT); - }, - }, - desc - ); -} - import { getID } from "@starbeam/shared"; interface TestResourceState { @@ -478,7 +248,7 @@ const TestResource = entryPointFn((description: string): TestResourceState => { return Wrap(cell, { id }, "TestResource"); }, description); - const resource = blueprint.create(parent); + const resource = use(blueprint, { lifetime: parent }); return { resource, @@ -686,7 +456,7 @@ class Steps { constructor(blueprint: ResourceBlueprint) { this.#owner = {}; this.blueprint = blueprint; - this.resource = blueprint.create(this.#owner); + this.resource = use(blueprint, { lifetime: this.#owner }); this.#state = this.resource.current; } From 21be030977cc158ed072770d5f8cc1ff468baffd Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 3 Apr 2023 10:29:49 -0700 Subject: [PATCH 18/46] Document `@starbeam/resource` + codebase GC --- packages/universal/resource/README.md | 175 +++++- .../universal/resource/src/resource-list.ts | 6 +- packages/universal/resource/src/resource.ts | 75 ++- packages/universal/resource/src/types.ts | 7 +- .../resource/tests/resource-list.spec.ts | 27 +- .../universal/resource/tests/resource.spec.ts | 112 ++-- packages/universal/universal/index.ts | 7 +- .../src/reactive-core/formula/linkable.ts | 24 - .../src/reactive-core/formula/setups.ts | 90 ---- .../higher-level/formula-list.ts | 31 ++ .../higher-level/resource-list.ts | 68 --- .../universal/src/reactive-core/into.ts | 25 +- .../universal/src/reactive-core/reactive.ts | 7 +- .../src/reactive-core/resource/core.ts | 0 .../resource/original-resource.ts | 230 -------- .../src/reactive-core/resource/run.ts | 54 -- .../src/reactive-core/resource/state.ts | 181 ------- .../reactive-core/resource/v2/constructor.ts | 43 -- .../src/reactive-core/resource/v2/index.ts | 9 - .../src/reactive-core/resource/v2/instance.ts | 49 -- .../resource/v2/resource-core.ts | 26 - .../src/reactive-core/resource/v2/run.ts | 50 -- .../src/reactive-core/resource/v2/state.ts | 122 ----- .../src/reactive-core/resource/v2/types.ts | 23 - .../src/reactive-core/resource/v3/README.md | 0 .../universal/src/reactive-core/service.ts | 10 +- .../tests/higher-level/resource-list.spec.ts | 144 ----- .../universal/tests/resource.spec.ts | 501 ------------------ .../universal/universal/tests/setup.spec.ts | 212 -------- workspace/eslint/src/base.js | 3 + 30 files changed, 327 insertions(+), 1984 deletions(-) delete mode 100644 packages/universal/universal/src/reactive-core/formula/linkable.ts delete mode 100644 packages/universal/universal/src/reactive-core/formula/setups.ts create mode 100644 packages/universal/universal/src/reactive-core/higher-level/formula-list.ts delete mode 100644 packages/universal/universal/src/reactive-core/higher-level/resource-list.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/core.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/original-resource.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/run.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/state.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/constructor.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/index.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/instance.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/run.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/state.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v2/types.ts delete mode 100644 packages/universal/universal/src/reactive-core/resource/v3/README.md delete mode 100644 packages/universal/universal/tests/higher-level/resource-list.spec.ts delete mode 100644 packages/universal/universal/tests/resource.spec.ts delete mode 100644 packages/universal/universal/tests/setup.spec.ts diff --git a/packages/universal/resource/README.md b/packages/universal/resource/README.md index d7592d28..673ed872 100644 --- a/packages/universal/resource/README.md +++ b/packages/universal/resource/README.md @@ -1,14 +1,72 @@ # Resources -At a basic level, resources are two-layer formulas: +A resource is a reactive constructor function with support for cleanup. -- A constructor formula that sets up the resource's instance (and registers - cleanup). The instance can (and usually does) have reactive state. -- An reactive instance that depends on the instance's state, and possibly other - reactive state. +```ts +import { Resource, use } from "@starbeam/resource"; +import { LIFETIME } from "@starbeam/runtime"; + +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return Formula(() => { + return new Intl.DateTimeFormat().format(now.current); + }); +}); + +const lifetime = {}; +const stopwatch = use(Stopwatch, { within: lifetime }); + +// later, when the lifetime is finalized... +LIFETIME.finalize(lifetime); +// the timer is cleared and `stopwatch` will stop updating +``` + +The `Resource` function takes a _resource constructor_ function and returns a +_resource blueprint_. A resource blueprint is instantiated with a _lifetime_ and +returns a _resource instance_. + +The resource constructor function is called with a _resource run_ object that +allows the resource constructor to register cleanup functions and create child +resources. + +The return value of the resource constructor is called the resource's _instance +value_. + +In this case, the resource instance (`stopwatch`) is a reactive value that +evaluates to the current time, formatted using `Intl.DateTimeFormat`. + +## Terms -This design creates a distinction between construction and instance -dependencies, which is critical for making the resource work. +
    +
    resource blueprint
    +
    The resource blueprint is instantiated with the `use` function and returns a resource instance
    +
    resource instance
    +
    An instance of a resource blueprint is called its resource instance.
    +
    instance value
    +
    The value returned by the resource constructor is called the instance value.
    +
    resource constructor
    +
    The function passed to the Resource function is called the resource constructor.
    +
    resource run
    +
    Each time the resource constructor runs for a given resource instance, it is called a resource run. The constructor is called with an instance of the resource run, which allows the constructor to register cleanup functions and create child resources.
    +
    + +## Assimilation + +A resource instance is always a stable reactive value. Its current value is the +most recent return value of its resource constructor. + +If a resource constructor returns a reactive value, the resource instance will +_assimilate_ that value. This means that the evaluated value of the resource +instance will be the same as the evaluated value of the returned reactive value. ```ts const Stopwatch = Resource(({ on }) => { @@ -28,8 +86,14 @@ const Stopwatch = Resource(({ on }) => { }); ``` -In this case, the construction formula has no reactive dependencies, but the -instance formula depends on the `now` cell. +In this case, the _resource run_ has no reactive dependencies, but the +_instance value_ is a formulaa that depends on the `now` cell. + +This means that instances of `Stopwatch` will be reactive values that evaluate +to the current time, formatted using `Intl.DateTimeFormat`, but the resource +constructor will only be evaluated once. + +### Regular Formulas Wouldn't Work Let's see what would happen if you tried to model this as a single formula: @@ -53,10 +117,77 @@ same formula, the formula invalidates every time the interval ticks, and the interval will be cleaned up and recreated on every tick. Definitely not what we wanted! -### Reactive Instance +## Resource Metadata -The second formula does not need to be a reactive value. For example, it could -be an instance of an object that stores a cell and exposes reactive getters: +In addition to state that's associated with each resource run, a resource can +have metadata that is shared across all resource runs. + +```ts +interface CounterMetadata { + interval: Reactive; + count: number; +} + +const Counter = Resource(({ on }, { metadata }: CounterMetadata)) => { + const count = Cell(metadata.count); + + const interval = setInterval(() => { + count.set(++metadata.count); + }, metadata.interval.current); + + on.cleanup(() => { + clearInterval(interval); + }); + + return count; +}; +``` + +When a resource has metadata, the initial value of the metadata is passed to the +`use` function as the second argument: + +```ts +const interval = Cell(1000); +const counter = use(Counter, { + within: lifetime, + metadata: { + interval, + count: 0, + }, +}); +``` + +Now, whenever the `interval` cell changes, the resource constructor will be +re-evaluated, but the `count` will be preserved. + +> In general, it's a good idea to avoid trying to maintain state across resource +> runs. It's sometimes necessary, but it maakes it possible to create resources +> with incoherent values, so you should try to think of an alternative if +> possible. + +## Semantics Summary + +1. A resource blueprint is instantiated with a _lifetime_ and returns a + _resource instance_. +2. When a resource run is evaluated: + 1. The previous resource run, if it exists, is finalized. + 2. Its constructor is evaluated as a formula, and its dependencies are the + dependencies of that formula. +3. When a resource instance's lifetime is finalized: + 1. Its current resource run is finalized. + 2. Any instance finalizers are run. +4. Whenever a resource instance is evaluated (i.e. its value is read): + 1. Its current resource run is validated. + 1. If it is invalid, a new resource run is created and the resource's + constructor is evaluated. + 2. If the instance value is a reactive value, the resource instance + is evaluated to the current value of that reactive value. + +### Instance Value + +While assimilation is often useful, a resource's instance value does not +**need** to be a reactive value. For example, it could be an instance of an +object that stores a cell and exposes reactive getters: ```ts const Stopwatch = Resource(({ on }) => { @@ -81,7 +212,7 @@ const Stopwatch = Resource(({ on }) => { Instances of `Stopwatch` are methods with a reactive `now` property which will change when the interval ticks. -## Resource Runs +## Resource Runs in More Detail A resource _instance_ is a long-lived reactive value that exists until the resource is finalized. A resource instance has a number of _resource runs_ over @@ -129,7 +260,7 @@ resources within the lifetime of the parent resource. There are several aspects of the design that make it easier to compose resources. -### Using a Resource Constructor +### Creating a Child Resource With `use` ```ts const Channel = Resource(({ use }) => { @@ -141,24 +272,22 @@ In this case, the Socket constructor is evaluated during `Channel`'s constructor, and its instance is linked to the current run. Whenever the current run is finalized, the Socket instance is finalized as well. +This `use` works just like the imported `use` function, except that you don't +specify a lifetime. Instead, the lifetime is the current resource run. + ### Reusing a Resource ```ts -const socket = Socket.create({ within: owner }); +const socket = use(Socket, { within: owner }); const Channel = Resource(({ use }) => { const socket = use(socket); }); ``` -In this case, `socket`'s lifetime is linked to the current run. Whenever the current -run is finalized, the Socket instance is finalized as well _unless_ it was -adopted by the next run. +In this case, `socket`'s lifetime is linked to the current run. Whenever the +current run is finalized, the Socket instance is finalized as well _unless_ it +was adopted by the next run. > `ResourceList` uses this feature to dynamically create child resources that are > automatically cleaned up when they aren't used anymore. - -## Resource Metadata - -A resource can also have instance metadata that lasts for the entire lifetime of -the resource. This metadata can be used for state that persists across runs. diff --git a/packages/universal/resource/src/resource-list.ts b/packages/universal/resource/src/resource-list.ts index 3ff09b19..8abe3fdf 100644 --- a/packages/universal/resource/src/resource-list.ts +++ b/packages/universal/resource/src/resource-list.ts @@ -16,7 +16,7 @@ export function ResourceList( ): ResourceBlueprint>[]> { const resources = new ResourceMap(); - return Resource((_, { lifetime }) => { + return Resource((_run, _metadata, lifetime) => { const result: Resource>[] = []; const remaining = new Set(); for (const item of list) { @@ -56,7 +56,9 @@ class ResourceMap { ): Resource> { const lifetime = {}; LIFETIME.link(parentLifetime, lifetime); - const newResource = use(resource, { lifetime }); + const newResource = use(resource, { + lifetime, + }); this.#map.set(key, { resource: newResource, lifetime }); return newResource; } diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index 400efe7a..c2dd3041 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -1,4 +1,4 @@ -import { DisplayStruct } from "@starbeam/debug"; +import { Desc, DisplayStruct } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; import { CachedFormula, @@ -57,9 +57,8 @@ export class ResourceRun { use = (( resource: UseResource, metadata?: unknown - ): FormulaFn => { - return use(resource, { metadata, lifetime: this }); - }) as UseMethod; + ): FormulaFn => + use(resource, { metadata, lifetime: this })) as UseMethod; } /** @@ -68,19 +67,24 @@ export class ResourceRun { */ export function use( resource: UseResource, - state: ResourceOptions + options: ResourceOptions ): Resource> { if (isFormulaFn(resource)) { return resource as Resource>; } else if (typeof resource === "function") { - return Resource(resource).use(state); + return useResourceConstructor(resource, options); } else { - return resource.use(state) as Resource>; + return useResourceConstructor( + ResourceBlueprint.Constructor(resource), + options + ); } } -type ResourceOptions = M extends void - ? Omit, "metadata"> +export type ResourceOptions = M extends void + ? Omit, "metadata"> & { + readonly metadata?: undefined; + } : ResourceState; interface ResourceState { @@ -96,23 +100,47 @@ interface ResourceState { readonly lifetime: object; } -export interface ResourceBlueprint { - use: (options: ResourceOptions) => Resource; -} +// export interface ResourceBlueprint { +// metadata: (metadata: M) => ResourceBlueprint; +// } export type Resource = FormulaFn; -export function Resource( - resource: ResourceConstructor, - _description?: string | Description -): ResourceBlueprint, M> { - return { - use: (options: ResourceOptions) => { - return useResourceConstructor(resource, options); - }, - }; +export class ResourceBlueprint { + static create( + this: void, + resource: ResourceConstructor, + description?: string | Description + ): ResourceBlueprint, M> { + return new ResourceBlueprint( + resource, + Desc("resource", description) + ) as ResourceBlueprint, M>; + } + + static Constructor( + blueprint: ResourceBlueprint + ): ResourceConstructor { + return blueprint.#Constructor; + } + + #Constructor: ResourceConstructor; + #description: Description; + + constructor(construct: ResourceConstructor, description: Description) { + this.#Constructor = construct; + this.#description = description; + } + + metadata(metadata: M): ResourceBlueprint { + return Resource((run, _, lifetime) => + this.#Constructor(run as ResourceRun, metadata, lifetime) + ) as ResourceBlueprint; + } } +export const Resource = ResourceBlueprint.create; + const RESOURCE_LIFETIMES = new WeakMap, object>(); export function lifetime(resource: Resource): object { @@ -128,10 +156,7 @@ function useResourceConstructor( const next = new ResourceRun(options); LIFETIME.link(options.lifetime, next); - const instance = resource(next, { - metadata: undefined, - ...options, - } as ResourceState); + const instance = resource(next, options.metadata as M, options.lifetime); // Finalize the previous run after running the new one to give the new one a // chance to adopt resources from the previous run. diff --git a/packages/universal/resource/src/types.ts b/packages/universal/resource/src/types.ts index 0e6d2848..fde71df4 100644 --- a/packages/universal/resource/src/types.ts +++ b/packages/universal/resource/src/types.ts @@ -23,7 +23,12 @@ export type ResourceConstructor = ( * of the resource, which ensures that it it will get cleaned up, at the * latest, when the resource itself is finalized. */ - resource: { metadata: M; lifetime: object } + resource: M, + + /** + * The `lifetime` parameter is the lifetime of the entire resource. + */ + lifetime: object ) => T; export type ResourceCleanup = (metadata: M) => void; diff --git a/packages/universal/resource/tests/resource-list.spec.ts b/packages/universal/resource/tests/resource-list.spec.ts index 8b4e3070..bc469fbb 100644 --- a/packages/universal/resource/tests/resource-list.spec.ts +++ b/packages/universal/resource/tests/resource-list.spec.ts @@ -104,17 +104,12 @@ describe("ResourceList", () => { }); test("should update resources", () => { - const list: Item[] = reactive.array([ + const items: Item[] = reactive.array([ { id: 1, name: "Tom", location: "NYC" }, { id: 2, name: "Chirag", location: "NYC" }, ]); - const map = ( - item: Item - ): ResourceBlueprint<{ - card: string; - subscription: Subscription; - }> => + const map = (item: Item) => Resource(({ on }) => { const subscription = new Subscription(item.name); subscription.connect(); @@ -132,15 +127,15 @@ describe("ResourceList", () => { const lifetime = { lifetime: "root" }; - const linkables = ResourceList(list, { + const List = ResourceList(items, { key: (item) => item.id, map, }); - const resources = use(linkables, { lifetime }); + const list = use(List, { lifetime }); function current(): { card: string; subscription: Subscription }[] { - return resources.current.map((r) => r.current); + return list.current.map((r) => r.current); } expect(current()).toEqual([ @@ -151,7 +146,7 @@ describe("ResourceList", () => { }, ]); - list.push({ id: 3, name: "John", location: "NYC" }); + items.push({ id: 3, name: "John", location: "NYC" }); let currentResources = current(); @@ -168,9 +163,9 @@ describe("ResourceList", () => { { card: "John (NYC)", subscription: { name: "John", isActive: true } }, ]); - list.pop(); + items.pop(); - expect(list).toEqual([ + expect(items).toEqual([ { id: 1, name: "Tom", location: "NYC" }, { id: 2, name: "Chirag", location: "NYC" }, ]); @@ -185,14 +180,14 @@ describe("ResourceList", () => { expect(john?.isActive).toBe(false); - list.reverse(); + items.reverse(); - expect(list).toEqual([ + expect(items).toEqual([ { id: 2, name: "Chirag", location: "NYC" }, { id: 1, name: "Tom", location: "NYC" }, ]); - currentResources = resources.current.map((r) => r.current); + currentResources = list.current.map((r) => r.current); expect(currentResources[0]?.subscription).toBe(chirag); expect(currentResources[1]?.subscription).toBe(tom); diff --git a/packages/universal/resource/tests/resource.spec.ts b/packages/universal/resource/tests/resource.spec.ts index 2ae22df7..e62c6112 100644 --- a/packages/universal/resource/tests/resource.spec.ts +++ b/packages/universal/resource/tests/resource.spec.ts @@ -76,25 +76,23 @@ describe("resources", () => { test("a counter that persists across cleanups", () => { const counts = { init: 0, finalized: 0 }; const invalidate = Marker(); - const Counter = Resource( - ({ on }, { metadata: count }: { metadata: Cell }) => { - invalidate.read(); - counts.init++; - - on.cleanup(() => { - counts.finalized++; - }); - - return { - get count() { - return count.current; - }, - increment() { - count.current++; - }, - }; - } - ); + const Counter = Resource(({ on }, count: Cell) => { + invalidate.read(); + counts.init++; + + on.cleanup(() => { + counts.finalized++; + }); + + return { + get count() { + return count.current; + }, + increment() { + count.current++; + }, + }; + }); const lifetime = {}; const counter = use(Counter, { lifetime, metadata: Cell(0) }); @@ -178,27 +176,25 @@ describe("resources", () => { const invalidateParent = Marker(); - const Parent = Resource( - ({ use }, { metadata: meta }: { metadata: { initHere: number } }) => { - const resource = use(child); - invalidateParent.read(); - meta.initHere++; - - return { - get state() { - return { - child: resource.current.state, - parent: { - init: meta.initHere, - }, - }; - }, - increment() { - resource.current.increment(); - }, - }; - } - ); + const Parent = Resource(({ use }, meta: { initHere: number }) => { + const resource = use(child); + invalidateParent.read(); + meta.initHere++; + + return { + get state() { + return { + child: resource.current.state, + parent: { + init: meta.initHere, + }, + }; + }, + increment() { + resource.current.increment(); + }, + }; + }); const lifetime = {}; const parent = use(Parent, { @@ -252,25 +248,23 @@ describe("resources", () => { const counts = { init: 0, finalized: 0 }; const invalidate = Marker(); - const Counter = Resource( - ({ on }, { metadata: count }: { metadata: Cell }) => { - invalidate.read(); - counts.init++; - - on.cleanup(() => { - counts.finalized++; - }); - - return { - get count() { - return count.current; - }, - increment() { - count.current++; - }, - }; - } - ); + const Counter = Resource(({ on }, count: Cell) => { + invalidate.read(); + counts.init++; + + on.cleanup(() => { + counts.finalized++; + }); + + return { + get count() { + return count.current; + }, + increment() { + count.current++; + }, + }; + }); const lifetime = {}; const counter = use(Counter, { lifetime, metadata: Cell(0) }); diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 7e4e473c..95aab6c8 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -5,13 +5,8 @@ export { CustomBuilder, } from "./src/reactive-core/custom.js"; export { Wrap } from "./src/reactive-core/delegate.js"; -export { Linkable } from "./src/reactive-core/formula/linkable.js"; -export { Setup, Setups } from "./src/reactive-core/formula/setups.js"; +export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; export { Freshness } from "./src/reactive-core/higher-level/freshness.js"; -export { - FormulaList, - ResourceList, -} from "./src/reactive-core/higher-level/resource-list.js"; export { Factory, type IntoReactiveObject, diff --git a/packages/universal/universal/src/reactive-core/formula/linkable.ts b/packages/universal/universal/src/reactive-core/formula/linkable.ts deleted file mode 100644 index 0a7ae1e7..00000000 --- a/packages/universal/universal/src/reactive-core/formula/linkable.ts +++ /dev/null @@ -1,24 +0,0 @@ -export class Linkable { - static create( - link: (owner: object, extra?: () => void) => T - ): Linkable { - return new Linkable(link); - } - - readonly #link: (owner: object, extra?: () => void) => T; - - private constructor(link: (link: object) => T) { - this.#link = link; - } - - create({ owner, extra }: { owner: object; extra?: () => void }): T { - return this.#link(owner, extra); - } - - map(mapper: (value: T) => U): Linkable { - return new Linkable((owner) => { - const value = this.#link(owner); - return mapper(value); - }); - } -} diff --git a/packages/universal/universal/src/reactive-core/formula/setups.ts b/packages/universal/universal/src/reactive-core/formula/setups.ts deleted file mode 100644 index 1bf77026..00000000 --- a/packages/universal/universal/src/reactive-core/formula/setups.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { type Description, descriptionFrom } from "@starbeam/debug"; -import { Formula, Marker } from "@starbeam/reactive"; -import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; -import { getID } from "@starbeam/shared"; - - -type SetupFunction = (() => void) | (() => () => void); -export type Setup = Formula; - -// TODO: I think that setups should ignore reads that are followed by writes. - -export function Setup( - setupFn: SetupFunction, - description?: string | Description -): Setup { - const desc = descriptionFrom({ - type: "formula", - api: { - package: "@starbeam/universal", - name: "Setup", - }, - fromUser: description, - }); - - let cleanup: (() => void) | void = undefined; - - const setup = Formula(() => { - if (cleanup) { - cleanup(); - } - - cleanup = setupFn(); - }, desc); - - LIFETIME.on.cleanup(setup, () => { - if (cleanup) { - cleanup(); - } - }); - - return setup; -} - -/** - * {@linkcode Setups} represents a collection of reactive setup functions that automatically clean - * themselves up and reinitialize whenever any of their dependencies invalidates. - * - * The {@linkcode Setups} itself is a {@linkcode ReactiveProtocol}, which means that other can - * subscribe to it in order to poll it for updates, which will result in the setup functions being - * reinitialized at a timing that is appropriate for the renderer using the {@linkcode Setups}. - */ - -export interface Setups { - register: (setupFn: SetupFunction, description: Description) => Unsubscribe; - setups: Formula; -} - -export function Setups(description: Description): Setups { - const setups = new Set(); - const marker = Marker({ - description: description.implementation(getID(), { - reason: "setups changed", - }), - }); - - const register = ( - setupFn: SetupFunction, - desc: Description - ): (() => void) => { - const setup = Setup(setupFn, desc); - const unsubscribe = LIFETIME.link(result, setup); - setups.add(setup); - - return () => { - setups.delete(setup); - unsubscribe(); - }; - }; - - const formula = Formula(() => { - marker.read(); - for (const setup of setups) { - setup(); - } - }, description); - - const result = { register, setups: formula }; - - return result; -} diff --git a/packages/universal/universal/src/reactive-core/higher-level/formula-list.ts b/packages/universal/universal/src/reactive-core/higher-level/formula-list.ts new file mode 100644 index 00000000..45bc22d0 --- /dev/null +++ b/packages/universal/universal/src/reactive-core/higher-level/formula-list.ts @@ -0,0 +1,31 @@ +import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; +import { CachedFormula, Formula } from "@starbeam/reactive"; + +export function FormulaList( + list: Iterable, + { + key, + map, + }: { + key: (item: T) => unknown; + map: (item: T) => U; + } +): Reactive { + const prev = new Map>(); + + return Formula(() => { + const result: U[] = []; + for (const item of list) { + const k = key(item); + const r = prev.get(k); + if (r) { + result.push(r.read()); + } else { + const newR = CachedFormula(() => map(item)); + result.push(newR.current); + prev.set(k, newR); + } + } + return result; + }); +} diff --git a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts b/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts deleted file mode 100644 index 61996acd..00000000 --- a/packages/universal/universal/src/reactive-core/higher-level/resource-list.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { CachedFormula, Formula } from "@starbeam/reactive"; - -import type { - AssimilatedResourceReturn, - ResourceBlueprint, - ResourceReturn, -} from "../resource/original-resource.js"; -import { Resource } from "../resource/original-resource.js"; - -export function ResourceList>( - list: Iterable, - { - key, - map, - }: { - key: (item: T) => unknown; - map: (item: T) => R; - } -): ResourceBlueprint[]> { - const prev = new Map(); - - return Resource(({ use }) => { - const result: ReactiveValue[] = []; - for (const item of list) { - const k = key(item); - const r = prev.get(k); - if (r) { - result.push(use(r)); - } else { - const newR = use(map(item)); - result.push(newR); - prev.set(k, newR); - } - } - - return result as AssimilatedResourceReturn[]; - }); -} - -export function FormulaList( - list: Iterable, - { - key, - map, - }: { - key: (item: T) => unknown; - map: (item: T) => U; - } -): Reactive { - const prev = new Map>(); - - return Formula(() => { - const result: U[] = []; - for (const item of list) { - const k = key(item); - const r = prev.get(k); - if (r) { - result.push(r.read()); - } else { - const newR = CachedFormula(() => map(item)); - result.push(newR.current); - prev.set(k, newR); - } - } - return result; - }); -} diff --git a/packages/universal/universal/src/reactive-core/into.ts b/packages/universal/universal/src/reactive-core/into.ts index d085d810..7867911f 100644 --- a/packages/universal/universal/src/reactive-core/into.ts +++ b/packages/universal/universal/src/reactive-core/into.ts @@ -1,24 +1,19 @@ import type { Description } from "@starbeam/debug"; import { Desc } from "@starbeam/debug"; import { intoReactive, isReactive } from "@starbeam/reactive"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; import type { ReactiveBlueprint } from "./reactive.js"; import { type Blueprint, Reactive, type ReactiveFactory } from "./reactive.js"; -import { ResourceBlueprint } from "./resource/original-resource.js"; -import { Resource, type ResourceFactory } from "./resource/original-resource.js"; -export type IntoResource = - | ResourceBlueprint - | ReactiveBlueprint - | ResourceFactory; +export type IntoResource = ResourceBlueprint | ReactiveBlueprint; -export type IntoResourceType> = I extends - | ResourceFactory - | ResourceBlueprint - ? ResourceBlueprint - : I extends ReactiveBlueprint | ReactiveFactory - ? ReactiveBlueprint - : never; +export type IntoResourceType> = + I extends ResourceBlueprint + ? ResourceBlueprint + : I extends ReactiveBlueprint | ReactiveFactory + ? ReactiveBlueprint + : never; export function IntoResource>( create: I, @@ -51,9 +46,7 @@ function resource( description?: Description | string ): Reactive { const desc = Desc("resource", description); - return intoReactive( - IntoResource(create as IntoResource, desc).create(owner) - ) as Reactive; + return intoReactive(IntoResource(create, desc).create(owner)) as Reactive; } export type IntoReactiveObject = ReactiveBlueprint | ReactiveFactory; diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index 9f8bcc5b..94d073ff 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -1,10 +1,9 @@ import { Desc, type Description } from "@starbeam/debug"; import type { ReactiveValue, Tag } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; +import type { ResourceBlueprint } from "@starbeam/resource"; import { isObject } from "@starbeam/verify"; -import type { ResourceBlueprint } from "./resource/original-resource.js"; - export type ReactiveFactory = | (() => T) | (new () => T) @@ -61,6 +60,4 @@ function construct(constructor: ReactiveFactory): T | Reactive { } } -export type Blueprint = - | ResourceBlueprint - | ReactiveBlueprint; +export type Blueprint = ResourceBlueprint | ReactiveBlueprint; diff --git a/packages/universal/universal/src/reactive-core/resource/core.ts b/packages/universal/universal/src/reactive-core/resource/core.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/universal/universal/src/reactive-core/resource/original-resource.ts b/packages/universal/universal/src/reactive-core/resource/original-resource.ts deleted file mode 100644 index 243df862..00000000 --- a/packages/universal/universal/src/reactive-core/resource/original-resource.ts +++ /dev/null @@ -1,230 +0,0 @@ -/** - * A Resource is a two-level formula: - * - * - The first formula is the "resource constructor". It is evaluated to produce - * the inner formula, and also has an opportunity to register finalizers and - * link children. - * - The inner formula is a regular formula. - * - * Whenever any dependencies of the first formula invalidate, the associated - * finalizers and children are finalized. - * - * The inner formula is stateless. This means it can be freely evaluated without - * worrying about its lifetime. - */ - -import { Desc, type Description } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; -import { CachedFormula, Static } from "@starbeam/reactive"; -import { LIFETIME } from "@starbeam/runtime"; -import { UNINITIALIZED } from "@starbeam/shared"; -import { isWeakKey } from "@starbeam/verify"; - -import type { IntoResource } from "../into.js"; -import { type Blueprint, ReactiveBlueprint } from "../reactive.js"; -import type { ResourceRun } from "./run.js"; -import { ResourceState } from "./state.js"; - -export type ResourceFactory = - | ((resource: ResourceRun) => ResourceReturn) - | (new (resource: ResourceRun) => ResourceReturn); - -/** - * {@linkcode ReactiveResource} is the stable value produced by instantiating a - * {@linkcode ResourceFactory}. - * - * Its primary purpose is to present a stable reactive value that is nonetheless internally changing - * quite a bit, and even getting cleaned up and reinitialized behind the scenes. - */ - -// TODO: Pass the `initial` value into the resource constructor, if an `initial` value exists. - -export function Resource( - create: ResourceBlueprint, - description?: string | Description -): ResourceBlueprint; -export function Resource( - create: ResourceFactory, - description?: string | Description -): ResourceBlueprint; -export function Resource( - create: IntoResource, - description?: string | Description -): Blueprint; -export function Resource( - create: IntoResource, - description?: string | Description -): Blueprint { - if ( - create instanceof ResourceBlueprint || - create instanceof ReactiveBlueprint - ) { - return create; - } - - const desc = Desc("resource", description); - - return new ResourceBlueprint( - (owner, initial) => { - // The resource state is shared between all runs of the resource. Each run is linked to it. The - // state itself is linked to the owner, so that it will be cleaned up when the owner is cleaned up. - const state = ResourceState.create(owner, create, initial, desc); - - LIFETIME.link(owner, state); - - return { state }; - }, - (run: ResourceRun, parent: ResourceState, initial) => { - { - const state = ResourceState.create(parent, create, initial, desc); - - const resource = state.resource; - - // If the parent run is finalized, finalize the resource, if it is still owned by the - // previous run. If it is adopted by a new run (which must have had the same parent - // ResourceState), the `.link` call on the next line will cause the resource to be - // adopted by the new run instead. - LIFETIME.link(run, resource, { root: ResourceState.getOwner(parent) }); - - return { state }; - } - }, - Static(UNINITIALIZED) - ); -} - -interface InternalBlueprintReturn { - state: ResourceState; -} - -export class ResourceBlueprint { - static initial( - blueprint: ResourceBlueprint - ): T | Default { - const current = blueprint.#initial.current; - - return current === UNINITIALIZED ? (undefined as Default) : current; - } - - #create: ( - owner: object, - initial: Reactive - ) => InternalBlueprintReturn; - #initial: Reactive | Reactive; - - #use: ( - run: ResourceRun, - parent: ResourceState, - initial: Reactive - ) => InternalBlueprintReturn; - - constructor( - create: ( - owner: object, - initial: Reactive - ) => InternalBlueprintReturn, - use: ( - run: ResourceRun, - parent: ResourceState, - initial: Reactive - ) => InternalBlueprintReturn, - initial: Reactive | Reactive - ) { - this.#create = create; - this.#use = use; - this.#initial = initial; - } - - create(owner: object): Resource { - return this.#link(this.#create(owner, this.#initial)); - } - - use(run: ResourceRun, parent: ResourceState): Resource { - return this.#link(this.#use(run, parent, this.#initial)); - } - - initial(value: () => T): ResourceBlueprint { - return new ResourceBlueprint(this.#create, this.#use, CachedFormula(value)); - } - - #link({ state }: InternalBlueprintReturn): Resource { - const resource = state.resource; - LIFETIME.link(resource, state); - return resource; - } - - root(): { resource: Resource; owner: object } { - const owner = Object.create(null) as object; - const resource = this.create(owner); - return { resource, owner }; - } - - isResource(): this is ResourceBlueprint { - return true; - } -} - -export type ResourceReturn = - | ResourceBlueprint - | Reactive - | T; - -type ResourceReturnType> = - R extends ResourceReturn ? V : never; - -export type AssimilatedResourceReturn> = - Ret extends ResourceBlueprint - ? Resource & Reactive> - : Ret extends Reactive - ? Reactive & Reactive> - : Ret extends Reactive - ? Reactive> - : Ret extends ResourceReturn - ? Reactive & Reactive - : never; - -declare const RESOURCE: unique symbol; - -const RESOURCES = new WeakMap(); - -export function isResource(value: ResourceReturn): value is Resource { - return !!(isWeakKey(value) && RESOURCES.get(value)?.hasLifetime); -} - -export function brandResource(reactive: Reactive): Resource { - RESOURCES.set(reactive, { hasLifetime: true }); - return reactive as unknown as Resource; -} - -export function brandReactiveResource(reactive: Reactive): Resource { - RESOURCES.set(reactive, { hasLifetime: false }); - return reactive as unknown as Resource; -} - -/** - * A Resource instance is a stable value, but it has multiple possible internal layers of - * invalidation. - * - * 1. The entire resource constructor can invalidate, which causes the resource to be cleaned up and - * the constructor to run again. If the resource is already set up, the setup function will run - * again once the resource is reinitialized. - * 2. Setup handlers can invalidate, which causes their cleanups to run, and then for the setup - * handers to run again. - * 3. The formula that represents the resource can invalidate, which simply causes the resource to - * invalidate. - * - * The trick of resources is providing a DSL that represents all of these three layers in a way that: - * - * 1. Naturally captures dependencies in all three layers. - * 2. Provides a lexical structure that naturally gives access to longer lived values inside of - * shorter-lived closures (e.g. the long-lived cells that power a resource are in the outermost - * scope; they can be used inside of setup handlers, and variables created inside setup handlers - * are available inside cleanup handlers). The goal is to avoid introducing unnecessary nulls or - * forcing inner callbacks to mutate outer-scope variables that are initialized to null or - * undefined. - */ -export interface Resource extends Reactive { - [RESOURCE]: true; -} - -export type Handler = (() => void) | (() => () => void); diff --git a/packages/universal/universal/src/reactive-core/resource/run.ts b/packages/universal/universal/src/reactive-core/resource/run.ts deleted file mode 100644 index addcd302..00000000 --- a/packages/universal/universal/src/reactive-core/resource/run.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Desc, type Description } from "@starbeam/debug"; -import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { LIFETIME, type Unsubscribe } from "@starbeam/runtime"; - -import type { Handler, Resource, ResourceBlueprint } from "./original-resource"; -import type { ResourceState } from "./state.js"; - -/** - * A `ResourceRun` represents a single run of a resource constructor. Whenever the dependencies of - * the previous run of the resource constructor change, a new `ResourceRun` is created and the - * previous one is finalized. - * - * If a resource that was used in this run was also used in the previous run, it will be adopted by - * the new run and not finalized. - */ - -const INITIAL_ID = 0; - -export class ResourceRun { - static getOwner(run: ResourceRun): object { - return run.#owner; - } - - static NEXT_ID = INITIAL_ID; - - readonly id: number; - readonly #desc: Description; - readonly #state: ResourceState; - readonly #owner: object; - - readonly on = { - cleanup: (handler: Handler): Unsubscribe => { - return LIFETIME.on.cleanup(this, handler); - }, - }; - - constructor(owner: object, state: ResourceState, desc: Description) { - this.#owner = owner; - this.#state = state; - this.#desc = desc; - this.id = ResourceRun.NEXT_ID++; - } - - readonly use = ( - resource: ResourceBlueprint | ReactiveValue | Resource | T, - options?: { description?: string | Description | undefined } - ): Reactive => { - return this.#state.assimilateResourceReturn({ - resource, - nextRun: this, - desc: Desc("resource", options?.description ?? this.#desc.detail("use")), - }) as Reactive; - }; -} diff --git a/packages/universal/universal/src/reactive-core/resource/state.ts b/packages/universal/universal/src/reactive-core/resource/state.ts deleted file mode 100644 index 4329075b..00000000 --- a/packages/universal/universal/src/reactive-core/resource/state.ts +++ /dev/null @@ -1,181 +0,0 @@ -import type { Description } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; -import { CachedFormula, isReactive, Static } from "@starbeam/reactive"; -import { LIFETIME } from "@starbeam/runtime"; -import { UNINITIALIZED } from "@starbeam/shared"; - -import { - type AssimilatedResourceReturn, - brandResource, - isResource, - type Resource, - ResourceBlueprint, - type ResourceFactory, - type ResourceReturn, -} from "./original-resource"; -import { ResourceRun } from "./run"; - -/** - * The `ResourceState` is the state that is shared between all runs of a resource. A single resource - * may invoke the resource constructor multiple times, but there is only a single `ResourceState`. - */ -export class ResourceState { - static getOwner(state: ResourceState): object { - return state.#owner; - } - - static create( - owner: object, - constructorFn: ResourceFactory, - initial: Reactive, - desc: Description - ): ResourceState { - function construct(run: ResourceRun): ResourceReturn { - try { - return ( - constructorFn as Extract< - ResourceFactory, - (run: ResourceRun) => unknown - > - )(run); - } catch (e) { - if (e instanceof TypeError && /class constructor/i.exec(e.message)) { - return new (constructorFn as Extract< - ResourceFactory, - new (run: ResourceRun) => unknown - >)(run); - } else { - throw e; - } - } - } - - const state = new ResourceState(desc, construct, initial, owner); - - return state; - } - - readonly #desc: Description; - readonly #constructorFn: (resource: ResourceRun) => ResourceReturn; - readonly #owner: object; - #currentRun: ResourceRun | undefined = undefined; - readonly reactiveConstructor: Reactive>; - readonly reactiveInstance: Reactive>; - readonly resource: Resource; - - constructor( - desc: Description, - constructorFn: (resource: ResourceRun) => ResourceReturn, - initial: Reactive, - owner: object - ) { - this.#desc = desc; - this.#constructorFn = constructorFn; - this.#owner = owner; - - this.reactiveConstructor = CachedFormula( - () => this.next(), - desc.detail("constructor") - ); - - let instance: Reactive | undefined = undefined; - let finalized = false; - - LIFETIME.on.cleanup(owner, () => { - finalized = true; - }); - - this.reactiveInstance = CachedFormula(() => { - if (instance && finalized) return instance; - - instance = this.reactiveConstructor.read(); - return instance; - }, desc.detail("instance")); - - this.resource = brandResource( - CachedFormula( - () => this.reactiveInstance.read().read(), - desc.detail("instance") - ) - ); - } - - /** - * Every time the resource constructor invalidates, this method is called to create a new - * `ResourceRun` by re-invoking the resource constructor. - * - * It also finalizes the previous `ResourceRun`, once the new constructor has run. Any resources - * that were used in the previous constructor and are used in the new constructor will be adopted - * by the new constructor and not finalized. - */ - next(): Reactive { - return this.#startNextRun((nextRun) => { - // Run the constructor function with the *new run*. We haven't yet finalized the previous run, - // so the constructor function has an opportunity to use any resources that were used in the - // previous run. - const returnValue = this.#constructorFn(nextRun); - - // Assimilate the return value into a resource. - // - // If the return value is a resource, we link it to the new run. It will get finalized when - // the new run is finalized, unless it is adopted by the new run. - // - // If the return value is a blueprint, we use it to create a new resource, which we then link - // to the new run. In this case, the blueprint will be finalized when the new run is - // finalized, as there is no way for the blueprint to be adopted by the new run. - return this.assimilateResourceReturn({ - resource: returnValue, - nextRun, - desc: this.#desc, - }) as Reactive; - }); - } - - #startNextRun(callback: (run: ResourceRun) => Reactive): Reactive { - const prevRun = this.#currentRun; - - const nextRun = new ResourceRun( - this.#owner, - this as ResourceState, - this.#desc - ); - this.#currentRun = nextRun; - - LIFETIME.link(this, nextRun); - - // We run the callback *before* we finalize the previous run, so that any resources that are - // used in the new run are adopted by the new run and therefore not finalized. - const result = callback(nextRun); - - prevRun && LIFETIME.finalize(prevRun); - - return result; - } - - assimilateResourceReturn, T>({ - resource, - nextRun, - desc, - }: { - resource: R; - nextRun: ResourceRun; - desc: Description; - }): AssimilatedResourceReturn { - if (isResource(resource)) { - LIFETIME.link(nextRun, resource, { root: this.#owner }); - return resource as AssimilatedResourceReturn; - } else if (isReactive(resource)) { - return resource as AssimilatedResourceReturn; - } else if (resource instanceof ResourceBlueprint) { - return resource.use(nextRun, this) as AssimilatedResourceReturn; - } else if (resource === UNINITIALIZED) { - return Static( - undefined - ) as Reactive as AssimilatedResourceReturn; - } else { - return Static(resource, { - description: desc.detail("return"), - }) as Reactive as AssimilatedResourceReturn; - } - } -} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/constructor.ts b/packages/universal/universal/src/reactive-core/resource/v2/constructor.ts deleted file mode 100644 index 00ed358b..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/constructor.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ResourceInstance } from "./instance.js"; -import { ResourceState } from "./state.js"; -import type { UpdateResource } from "./types.js"; - -export class ResourceConstructorImpl { - static create( - this: void, - metadata: M, - update: UpdateResource - ): ResourceConstructor { - return new ResourceConstructorImpl(update, metadata); - } - - readonly #metadata: M; - readonly #update: UpdateResource; - - constructor(update: UpdateResource, metadata: M) { - this.#metadata = metadata; - this.#update = update; - } - - create({ within }: { within: object }): ResourceInstance { - const state = ResourceState.create(this.#update, this.#metadata, within); - return ResourceInstance.create(state, within); - } - - use({ - within, - root, - }: { - within: object; - root: object; - }): ResourceInstance { - const state = ResourceState.scoped(this.#update, this.#metadata, { - owner: within, - root, - }); - return ResourceInstance.create(state, within); - } -} - -export type ResourceConstructor = ResourceConstructorImpl; -export const ResourceConstructor = ResourceConstructorImpl.create; diff --git a/packages/universal/universal/src/reactive-core/resource/v2/index.ts b/packages/universal/universal/src/reactive-core/resource/v2/index.ts deleted file mode 100644 index 029d5add..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { ResourceConstructor } from "./constructor.js"; -export { ResourceInstance } from "./instance.js"; -export { - assimilateResource, - getRunInstance, - updateResource, -} from "./resource-core.js"; -export { CreateResourceRun } from "./run.js"; -export { ResourceState } from "./state.js"; diff --git a/packages/universal/universal/src/reactive-core/resource/v2/instance.ts b/packages/universal/universal/src/reactive-core/resource/v2/instance.ts deleted file mode 100644 index 4caf0309..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/instance.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { Reactive } from "@starbeam/interfaces"; -import { CachedFormula } from "@starbeam/reactive"; - -import type { ResourceState } from "./state.js"; -import type { Assimilate, RunResult } from "./types.js"; - -export class ResourceInstance { - static create( - state: ResourceState, - root: object - ): ResourceInstance { - return new ResourceInstance( - state, - CachedFormula(() => state.nextRun()), - root - ); - } - - readonly #state: ResourceState; - readonly #instance: Reactive>; - readonly #root: object; - - private constructor( - state: ResourceState, - resourceInstance: Reactive>, - root: object - ) { - this.#state = state; - this.#instance = resourceInstance; - this.#root = root; - } - - adopt(parent: object): void { - this.#state.adopt(parent, { root: this.#root }); - } - - metadata(): Reactive { - return CachedFormula(() => this.#instance.current.value.metadata); - } - - instance(): Reactive; - instance(fn: Assimilate): Reactive; - instance(fn?: Assimilate): Reactive { - return CachedFormula(() => { - const instance = this.#instance.current.value.instance; - return fn ? fn(instance) : instance; - }); - } -} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts b/packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts deleted file mode 100644 index e5d49973..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/resource-core.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Reactive } from "@starbeam/interfaces"; -import { isReactive } from "@starbeam/reactive"; - -import type { RunResult, UpdateResource } from "./types.js"; - -export type Cleanup = (metadata: M) => void; - -export function assimilateResource(value: T | Reactive): T { - if (isReactive(value)) { - return value.current; - } else { - return value; - } -} - -export function getRunInstance( - result: Reactive> -): T | undefined { - return result.current.value.instance; -} - -export function updateResource( - updater: UpdateResource -): UpdateResource { - return updater; -} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/run.ts b/packages/universal/universal/src/reactive-core/resource/v2/run.ts deleted file mode 100644 index 3ec885e6..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/run.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { Unsubscribe } from "@starbeam/interfaces"; -import { LIFETIME } from "@starbeam/runtime"; - -import { ResourceConstructorImpl } from "./constructor.js"; -import type { ResourceInstance } from "./instance.js"; -import type { ResourceConstructor } from "./types.js"; - -type Cleanup = (metadata: M) => void; - -export class CreateResourceRun { - static create(metadata: M, root: object): CreateResourceRun { - return new CreateResourceRun(metadata, root); - } - - readonly #metadata: M; - readonly #root: object; - readonly #cleanups = new Set>(); - - private constructor(metadata: M, root: object) { - this.#metadata = metadata; - this.#root = root; - LIFETIME.on.cleanup(this, () => { - this.#cleanup(); - }); - } - - readonly on = { - cleanup: (fn: (metadata: M) => void): Unsubscribe => { - this.#cleanups.add(fn as Cleanup); - return () => this.#cleanups.delete(fn as Cleanup); - }, - }; - - use = ( - resource: ResourceConstructor | ResourceInstance - ): ResourceInstance => { - if (resource instanceof ResourceConstructorImpl) { - return resource.use({ within: this, root: this.#root }); - } else { - resource.adopt(this.#root); - return resource; - } - }; - - #cleanup(): void { - for (const cleanup of this.#cleanups) { - cleanup(this.#metadata); - } - } -} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/state.ts b/packages/universal/universal/src/reactive-core/resource/v2/state.ts deleted file mode 100644 index b278d93b..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/state.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { LIFETIME } from "@starbeam/runtime"; -import { UNINITIALIZED } from "@starbeam/shared"; -import { isNotEqual, verified } from "@starbeam/verify"; - -import { CreateResourceRun } from "./run.js"; -import type { ExposedFinalized, RunResult, UpdateResource } from "./types.js"; - -export class ResourceState { - static create( - update: UpdateResource, - metadata: M, - owner = {} - ): ResourceState { - const state = new ResourceState(update, metadata, owner); - LIFETIME.link(owner, state); - return state; - } - - static scoped( - update: UpdateResource, - metadata: M, - { owner, root }: { owner: object; root: object } - ): ResourceState { - const state = new ResourceState(update, metadata, owner); - LIFETIME.link(owner, state, { root }); - return state; - } - - /** - * The root lifetime of a resource is the lifetime of the top resource in a - * resource tree. Resources created within the root (via `use`) will be - * automatically adopted from one run to the next. - */ - #root: object; - #instance: T | UNINITIALIZED = UNINITIALIZED; - readonly #metadata: M; - readonly #update: UpdateResource; - #run: CreateResourceRun | null = null; - - /** - * Once the resource is finalized, its `nextRun` method will return - * `{done: true, metadata: metadata}`. - */ - #isFinalized = false; - - private constructor(update: UpdateResource, metadata: M, root: object) { - this.#update = update as UpdateResource; - this.#metadata = metadata; - this.#root = root; - - LIFETIME.on.cleanup(this, () => { - this.#isFinalized = true; - }); - } - - get #lastInstance(): T { - // The only way for this to happen is if the resource is finalized before it - // was ever consumed, and then it is consumed later. This should be avoided - // by construction, but there is still some work to do there. - return verified(this.#instance, isNotEqual(UNINITIALIZED)); - } - - adopt(parent: object, { root }: { root: object }): void { - LIFETIME.link(parent, this, { root }); - } - - nextRun(): RunResult { - if (this.#isFinalized) { - return finalized(this.#lastInstance, this.#metadata); - } - - const prevRun = this.#run; - - const run = this.#createRun(); - const result = next(this.#update(run, this.#metadata), this.#metadata); - this.#instance = result.value.instance; - - if (prevRun) LIFETIME.finalize(prevRun); - - return result; - } - - #createRun(): CreateResourceRun { - const run = (this.#run = CreateResourceRun.create( - this.#metadata, - this.#root - )); - LIFETIME.link(this, run); - return run; - } - - get isFinalized(): boolean { - return this.#isFinalized; - } - - get metadata(): M { - return this.#metadata; - } -} - -function next(instance: T, metadata: M): RunResult { - return { - done: false, - value: { - instance, - metadata, - }, - }; -} - -function finalized( - instance: T, - metadata: M -): { done: true; value: ExposedFinalized } { - return { - done: true, - value: { - instance, - metadata, - }, - }; -} diff --git a/packages/universal/universal/src/reactive-core/resource/v2/types.ts b/packages/universal/universal/src/reactive-core/resource/v2/types.ts deleted file mode 100644 index 7aa86967..00000000 --- a/packages/universal/universal/src/reactive-core/resource/v2/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { CreateResourceRun } from "./run.js"; - -export type Cleanup = (metadata: M) => void; -export type UpdateResource = ( - run: CreateResourceRun, - metadata: M -) => T; -export type RunResult = IteratorResult< - Exposed, - ExposedFinalized ->; -export { ResourceConstructor } from "./constructor.js"; -export type Assimilate = (value: T) => U; - -export interface ExposedFinalized { - readonly instance: T; - readonly metadata: M; -} - -export interface Exposed { - readonly instance: T; - readonly metadata: M; -} diff --git a/packages/universal/universal/src/reactive-core/resource/v3/README.md b/packages/universal/universal/src/reactive-core/resource/v3/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/universal/universal/src/reactive-core/service.ts b/packages/universal/universal/src/reactive-core/service.ts index 3074b85c..5c3b93ce 100644 --- a/packages/universal/universal/src/reactive-core/service.ts +++ b/packages/universal/universal/src/reactive-core/service.ts @@ -1,20 +1,20 @@ import { Desc } from "@starbeam/debug"; import type { Description, Reactive } from "@starbeam/interfaces"; +import type { ResourceBlueprint } from "@starbeam/resource"; import { CONTEXT } from "@starbeam/runtime"; import { Factory, type IntoResource } from "./into.js"; import type { Blueprint } from "./reactive.js"; -import type { ResourceFactory } from "./resource/original-resource.js"; export function Service( - create: Blueprint | ResourceFactory, + create: Blueprint, description?: string | Description ): ServiceBlueprint { return new ServiceBlueprint(create, Desc("blueprint:service", description)); } Service.create = ( - create: Blueprint | ResourceFactory, + create: Blueprint, description?: string | Description ): Reactive => { return createService(create, Desc("service", description)); @@ -46,14 +46,14 @@ export function createService( } export function reactiveService( - factory: Blueprint | ResourceFactory, + factory: Blueprint | ResourceBlueprint, description?: string | Description ): Reactive { return createService(factory, Desc("service", description)); } export function service( - factory: Blueprint | ResourceFactory, + factory: Blueprint, description?: string | Description ): T { return createService(factory, Desc("service", description)).current; diff --git a/packages/universal/universal/tests/higher-level/resource-list.spec.ts b/packages/universal/universal/tests/higher-level/resource-list.spec.ts deleted file mode 100644 index 607ab57c..00000000 --- a/packages/universal/universal/tests/higher-level/resource-list.spec.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { DisplayStruct } from "@starbeam/debug"; -import { reactive } from "@starbeam/js"; -import { - Formula, - Resource, - type ResourceBlueprint, - ResourceList, -} from "@starbeam/universal"; -import { describe, expect, test } from "@starbeam-workspace/test-utils"; - -interface Item { - id: number; - name: string; - location: string; -} - -class Subscription { - #active = true; - declare readonly isActive: boolean; - - constructor(readonly name: string) { - Object.defineProperty(this, "isActive", { - enumerable: true, - get: () => { - return this.#active; - }, - }); - } - - [Symbol.for("nodejs.util.inspect.custom")](): object { - return DisplayStruct("Subscription", { - name: this.name, - isActive: this.isActive, - }); - } - - connect(): void { - this.#active = true; - } - - disconnect(): void { - this.#active = false; - } -} - -describe("ResourceList", () => { - test("should update resources", () => { - const list: Item[] = reactive.array([ - { id: 1, name: "Tom", location: "NYC" }, - { id: 2, name: "Chirag", location: "NYC" }, - ]); - - const map = ( - item: Item - ): ResourceBlueprint<{ - card: string; - subscription: Subscription; - }> => - Resource(({ on }) => { - const subscription = new Subscription(item.name); - subscription.connect(); - - on.cleanup(() => { - subscription.disconnect(); - }); - - return Formula(() => ({ - card: `${subscription.name} (${item.location})`, - subscription: subscription, - })); - }, `subscription for '${item.name}' (${item.id})`); - - const lifetime = {}; - - const linkables = ResourceList(list, { - key: (item) => item.id, - map, - }); - - const resources = linkables.create({ owner: lifetime }); - - expect(resources.current.map((r) => r.current)).toEqual([ - { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, - { - card: "Chirag (NYC)", - subscription: { name: "Chirag", isActive: true }, - }, - ]); - - list.push({ id: 3, name: "John", location: "NYC" }); - - let currentResources = resources.current.map((r) => r.current); - - const tom = currentResources[0]?.subscription; - const chirag = currentResources[1]?.subscription; - const john = currentResources[2]?.subscription; - - expect(resources.current.map((r) => r.current)).toEqual([ - { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, - { - card: "Chirag (NYC)", - subscription: { name: "Chirag", isActive: true }, - }, - { card: "John (NYC)", subscription: { name: "John", isActive: true } }, - ]); - - list.pop(); - - expect(list).toEqual([ - { id: 1, name: "Tom", location: "NYC" }, - { id: 2, name: "Chirag", location: "NYC" }, - ]); - - expect(resources.current.map((r) => r.current)).toEqual([ - { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, - { - card: "Chirag (NYC)", - subscription: { name: "Chirag", isActive: true }, - }, - ]); - - expect(john?.isActive).toBe(false); - - list.reverse(); - - expect(list).toEqual([ - { id: 2, name: "Chirag", location: "NYC" }, - { id: 1, name: "Tom", location: "NYC" }, - ]); - - currentResources = resources.current.map((r) => r.current); - - expect(currentResources[0]?.subscription).toBe(chirag); - expect(currentResources[1]?.subscription).toBe(tom); - - expect(currentResources).toEqual([ - { - card: "Chirag (NYC)", - subscription: { name: "Chirag", isActive: true }, - }, - { card: "Tom (NYC)", subscription: { name: "Tom", isActive: true } }, - ]); - }); -}); diff --git a/packages/universal/universal/tests/resource.spec.ts b/packages/universal/universal/tests/resource.spec.ts deleted file mode 100644 index 09602fad..00000000 --- a/packages/universal/universal/tests/resource.spec.ts +++ /dev/null @@ -1,501 +0,0 @@ -import { - callerStack, - DisplayStruct, - entryPointFn, - entryPoints, -} from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; -import { - Cell, - Formula, - LIFETIME, - Resource, - type ResourceBlueprint, - use, - Wrap, -} from "@starbeam/universal"; -import { exhaustive } from "@starbeam/verify"; -import { describe, expect, test } from "vitest"; - -const INITIAL_ID = 0; - -class Socket { - static #nextId = INITIAL_ID; - - static subscribe(name: string): Socket { - return new Socket(name, true); - } - - readonly id: string; - readonly #name: string; - #active: boolean; - - constructor(name: string, active: boolean) { - this.id = String(Socket.#nextId++); - this.#name = name; - this.#active = active; - } - - get name(): string { - return this.#name; - } - - get isActive(): boolean { - return this.#active; - } - - [Symbol.for("nodejs.util.inspect.custom")](): object { - return DisplayStruct("Socket", { - id: this.id, - name: this.#name, - active: this.#active, - }); - } - - disconnect(): void { - this.#active = false; - } -} - -Subscription({ username: "@tomdale", channel: "emails" }) - .describe( - "a resource is a formula with lifetime", - (start, { username, channel }) => - start(({ assert }) => { - assert.initial({ - description: "@tomdale @ emails", - name: "emails", - state: "active", - }); - }) - .step( - "updating a dependency of the resource instance that is *not* a dependency of the resource constructor", - () => username.set("@todale"), - ({ assert }) => { - assert.unstable(); - assert.socket.isStable({ - state: "active", - name: "emails", - description: "@todale @ emails", - }); - } - ) - .step( - "updating a dependency of the resource constructor", - () => channel.set("twitter"), - ({ assert }) => { - assert.unstable(); - assert.socket.changed({ - state: "active", - name: "twitter", - description: "@todale @ twitter", - }); - } - ) - .finalize(({ assert }) => { - assert.isFinalized({ - state: "finalized", - name: "twitter", - description: "@todale @ twitter", - }); - }) - ) - .describe("the resource can be cleaned up early", (start, { channel }) => - start(({ assert }) => { - assert.initial({ - description: "@tomdale @ emails", - name: "emails", - state: "active", - }); - }) - .finalize(({ assert }) => { - assert.unstable(); - assert.socket.isStable({ - state: "finalized", - name: "emails", - description: "@tomdale @ emails", - }); - }) - .step( - "setting a dependency of the resource after it was finalized doesn't re-run the constructor", - () => channel.set("twitter"), - ({ assert }) => { - assert.unstable(); - assert.socket.isStable({ - state: "finalized", - name: "emails", - description: "@tomdale @ twitter", - }); - } - ) - ); - -const INITIAL_COUNT = 0; -const INCREMENT = 1; - -describe("use()", () => { - test("using a resource in a previous run but not this one causes it to be cleaned up", () => { - const Inner = Resource(({ on }) => { - const cell = Cell("active"); - - on.cleanup(() => { - cell.set("finalized"); - }); - - return cell; - }, "Inner"); - - const counter = Cell(INITIAL_COUNT, { description: "i" }); - let run = 0; - let currentInstance = undefined as Reactive | undefined; - let prevInner = undefined as Reactive | undefined; - - const outer = Resource(({ use }) => { - prevInner = currentInstance; - const next = (currentInstance = use(Inner)); - const currentRun = run++; - - // intentionally do this at the top level so that the resource constructor is invalidated. - const currentI = counter.current; - - return Formula( - () => `${next.current} (run = ${currentRun}, i = ${currentI})`, - { description: "OuterFormula" } - ); - }, "Outer"); - - const parent = {}; - - const instance = use(outer, { lifetime: parent }); - - expect(instance.current).toBe("active (run = 0, i = 0)"); - expect(prevInner?.current).toBe(undefined); - - counter.update((i) => i + INCREMENT); - expect(instance.current).toBe("active (run = 1, i = 1)"); - expect(prevInner?.current).toBe("finalized"); - - counter.update((i) => i + INCREMENT); - expect(instance.current).toBe("active (run = 2, i = 2)"); - expect(prevInner?.current).toBe("finalized"); - }); - - test("transferring a resource prevents it from being cleaned up", () => { - const { resource: inner } = TestResource("inner"); - - const outerDep = Cell(INITIAL_COUNT, { description: "OuterDep" }); - const formulaDep = Cell(INITIAL_COUNT, { description: "FormulaDep" }); - - const Outer = Resource(({ use, on }) => { - const innerValue = use(inner); - - expect(innerValue).toBe(inner); - - const cell = Cell(`outer: active (${outerDep.current})`); - - on.cleanup(() => { - cell.set("outer: finalized"); - }); - - return Formula( - () => - `${cell.current}, ${innerValue.current}, formula-dep: ${formulaDep.current}`, - { description: "Outer Formula" } - ); - }, "Outer"); - - const lifetime = {}; - const outer = use(Outer, { lifetime }); - - expect(outer.current).toBe( - "outer: active (0), inner: active, formula-dep: 0" - ); - - formulaDep.update((i) => i + INCREMENT); - - expect(outer.current).toBe( - "outer: active (0), inner: active, formula-dep: 1" - ); - expect(inner.current).toBe("inner: active"); - - outerDep.update((i) => i + INCREMENT); - - expect(outer.current).toBe( - "outer: active (1), inner: active, formula-dep: 1" - ); - }); -}); - -import { getID } from "@starbeam/shared"; - -interface TestResourceState { - resource: Resource; - blueprint: ResourceBlueprint; - parent: object; -} - -const TestResource = entryPointFn((description: string): TestResourceState => { - const parent = Object.create(null) as object; - - const blueprint = Resource(({ on }) => { - const id = getID(); - const cell = Cell(`${description}: active`); - - on.cleanup(() => { - cell.set(`${description}: finalized`); - }); - - return Wrap(cell, { id }, "TestResource"); - }, description); - - const resource = use(blueprint, { lifetime: parent }); - - return { - resource, - blueprint, - parent, - }; -}); - -type ResourceStatus = "did construct" | "did cleanup"; - -interface ResourceState { - readonly status: ResourceStatus; - readonly socket: Socket; - readonly description: string; -} - -interface DescribeSubscription { - describe: ( - name: string, - callback: ( - start: (this: void, assert: (state: StepState) => void) => Steps, - cells: { username: Cell; channel: Cell } - ) => void - ) => DescribeSubscription; -} - -function Subscription({ - username: u, - channel: c, -}: { - username: string; - channel: string; -}): DescribeSubscription { - const username = Cell(u); - const channel = Cell(c); - - const resource = Resource(({ on }) => { - const socket = Socket.subscribe(channel.current); - const status = Cell("did construct" as ResourceStatus); - - on.cleanup(() => { - status.set("did cleanup"); - socket.disconnect(); - }); - - return Formula(() => { - return { - status: status.current, - socket, - description: `${username.current} @ ${channel.current}`, - }; - }); - }); - - return { - describe( - name: string, - callback: ( - start: (this: void, assert: (state: StepState) => void) => Steps, - cells: { username: Cell; channel: Cell } - ) => void - ): DescribeSubscription { - function start(this: void, assert: (state: StepState) => void): Steps { - const stack = callerStack(); - const steps = new Steps(resource); - - test( - "initial state", - entryPointFn( - () => { - assert(new StepState(undefined, steps.resource.current)); - }, - { stack } - ) - ); - return steps; - } - - describe(name, () => { - callback(start, { username, channel }); - }); - return Subscription({ username: u, channel: c }); - }, - }; -} - -type StateAssertion = { state: "active" } | { state: "finalized" }; - -interface DetailsAssertion { - name: string; - description: string; -} - -type Postcondition = StateAssertion & DetailsAssertion; - -class StepState { - assert = entryPoints({ - equivalent: () => { - expect(this.prev).toEqual(this.state); - }, - - initial: (condition: Postcondition) => { - expect(this.prev, "the previous resource state").toBeUndefined(); - this.#assert(condition); - }, - - stable: (condition: Postcondition) => { - expect(this.prev, "the previous resource state").toBe(this.state); - this.#assert(condition); - }, - - unstable: () => { - expect(this.prev).not.toBe(this.state); - }, - - description: (description: string) => { - expect(this.state.description, "the current description").toBe( - description - ); - }, - - isActive: () => { - this.#assertState({ state: "active" }); - }, - - isFinalized: (condition: Postcondition) => { - this.#assertState({ state: "finalized" }); - this.#assert(condition); - }, - - socket: entryPoints({ - isStable: (condition: Postcondition) => { - this.#assertStableSocket(); - this.#assert(condition); - }, - - changed: (condition: Postcondition) => { - this.#assertUnstableSocket(); - this.#assert(condition); - }, - }), - }); - - constructor( - readonly prev: ResourceState | undefined, - readonly state: ResourceState - ) {} - - #assertStatus(status: ResourceStatus, state = this.state): void { - expect(state.status, "the resource's status").toBe(status); - } - - #assertSocketActive(isActive: boolean, state = this.state): void { - expect(state.socket?.isActive, "the socket's active state").toBe(isActive); - } - - #assertStableSocket(): void { - expect(this.prev?.socket, "the previous socket").toBe(this.state.socket); - } - - #assertUnstableSocket(): void { - expect(this.prev?.socket, "the previous socket").not.toBe( - this.state.socket - ); - } - - #assertState(options: StateAssertion, state = this.state): void { - switch (options.state) { - case "active": - this.#assertStatus("did construct", state); - this.#assertSocketActive(true, state); - break; - case "finalized": - this.#assertStatus("did cleanup", state); - this.#assertSocketActive(false, state); - this.#assertStableSocket(); - break; - default: - exhaustive(options); - } - } - - #assertDetails(options: DetailsAssertion, state = this.state): void { - expect(state.description, "the resource's description").toBe( - options.description - ); - expect(state.socket?.name, "the resource's name").toBe(options.name); - } - - #assert( - options: StateAssertion & DetailsAssertion, - state = this.state - ): void { - this.#assertState(options, state); - this.#assertDetails(options, state); - } -} - -class Steps { - #state: ResourceState; - #owner: object; - readonly blueprint: ResourceBlueprint; - readonly resource: Reactive; - - constructor(blueprint: ResourceBlueprint) { - this.#owner = {}; - this.blueprint = blueprint; - this.resource = use(blueprint, { lifetime: this.#owner }); - this.#state = this.resource.current; - } - - step( - description: string, - action: (options: { resource: Reactive }) => void, - assert: (options: StepState) => void - ): this { - const stack = callerStack(); - test( - description, - entryPointFn( - () => { - const prev = this.#state; - action({ resource: this.resource }); - this.#state = this.resource.current; - assert(new StepState(prev, this.#state)); - }, - { stack } - ) - ); - - return this; - } - - finalize(assert: (options: StepState) => void): this { - test( - "finalizing", - entryPointFn( - () => { - const prev = this.#state; - LIFETIME.finalize(this.#owner); - this.#state = this.resource.current; - assert(new StepState(prev, this.#state)); - return this; - }, - { stack: callerStack() } - ) - ); - return this; - } -} diff --git a/packages/universal/universal/tests/setup.spec.ts b/packages/universal/universal/tests/setup.spec.ts deleted file mode 100644 index d459d4f2..00000000 --- a/packages/universal/universal/tests/setup.spec.ts +++ /dev/null @@ -1,212 +0,0 @@ -import { getTag } from "@starbeam/tags"; -import { Cell, PUBLIC_TIMELINE, Setup } from "@starbeam/universal"; -import { describe, expect, test } from "vitest"; - -describe("Setup", () => { - test("setup without cleanup", () => { - let variable = { cell: 0, counter: 0 }; - let counter = 0; - const cell = Cell(0); - - const setup = Setup((): void => { - variable = { cell: cell.current, counter: ++counter }; - }); - - expect(variable).toEqual({ - cell: 0, - counter: 0, - }); - - setup(); - - expect(variable).toEqual({ - cell: 0, - counter: 1, - }); - - setup(); - - expect(variable).toEqual({ - cell: 0, - counter: 1, - }); - - cell.set(1); - - expect(variable).toEqual({ - cell: 0, - counter: 1, - }); - - setup(); - expect(variable).toEqual({ - cell: 1, - counter: 2, - }); - }); - - test("setup with cleanup", () => { - let variable = { cell: 0, counter: 0, pairCounter: 0 }; - let counter = 0; - let pairCounter = 0; - const cell = Cell(0); - - const setup = Setup(() => { - pairCounter++; - variable = { cell: cell.current, counter: ++counter, pairCounter }; - - return () => { - pairCounter--; - variable.pairCounter = pairCounter; - }; - }); - - expect(variable).toEqual({ - cell: 0, - counter: 0, - pairCounter: 0, - }); - - setup(); - - expect(variable).toEqual({ - cell: 0, - counter: 1, - pairCounter: 1, - }); - - setup(); - - expect(variable).toEqual({ - cell: 0, - counter: 1, - pairCounter: 1, - }); - - cell.set(1); - - expect(variable).toEqual({ - cell: 0, - counter: 1, - pairCounter: 1, - }); - - setup(); - - expect(variable).toEqual({ - cell: 1, - counter: 2, - pairCounter: 1, - }); - }); - - test("setup is reactive", () => { - let variable = { cell: 0, setupCounter: 0, cleanupCounter: 0 }; - let setupCounter = 0; - let cleanupCounter = 0; - const cellA = Cell(0); - const cellB = Cell(10); - - const setup = Setup(() => { - setupCounter++; - variable = { - cell: cellA.current % 2 === 0 ? cellA.current : cellB.current, - setupCounter, - cleanupCounter: cleanupCounter, - }; - - return () => { - cleanupCounter++; - variable.cleanupCounter = cleanupCounter; - }; - }); - - let ts = PUBLIC_TIMELINE.now; - - expect(variable).toEqual({ - cell: 0, - setupCounter: 0, - cleanupCounter: 0, - }); - - expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); - - setup(); - - expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); - - expect(variable).toEqual({ - cell: 0, - setupCounter: 1, - cleanupCounter: 0, - }); - - // cellB is not used in the initial setup, so it doesn't invalidate the setup - cellB.set(20); - expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); - - setup(); - - expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); - - expect(variable).toEqual({ - cell: 0, - setupCounter: 1, - cleanupCounter: 0, - }); - - cellA.set(1); - - expect(getTag(setup).lastUpdated).toSatisfy(gt(ts)); - ts = getTag(setup).lastUpdated; - - expect(variable).toEqual({ - cell: 0, - setupCounter: 1, - cleanupCounter: 0, - }); - - setup(); - - expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); - - expect(variable).toEqual({ - cell: 20, - setupCounter: 2, - cleanupCounter: 1, - }); - - cellA.set(2); - - expect(getTag(setup).lastUpdated).toSatisfy(gt(ts)); - ts = getTag(setup).lastUpdated; - - expect(variable).toEqual({ - cell: 20, - setupCounter: 2, - cleanupCounter: 1, - }); - - setup(); - - expect(getTag(setup).lastUpdated).toSatisfy(eq(ts)); - - expect(variable).toEqual({ - cell: 2, - setupCounter: 3, - cleanupCounter: 2, - }); - }); -}); - -function eq boolean }>( - other: T -): (value: T) => boolean { - return (value: T) => value.eq(other); -} - -function gt boolean }>( - other: T -): (value: T) => boolean { - return (value: T) => value.gt(other); -} diff --git a/workspace/eslint/src/base.js b/workspace/eslint/src/base.js index 66c5d911..6225c559 100644 --- a/workspace/eslint/src/base.js +++ b/workspace/eslint/src/base.js @@ -78,6 +78,9 @@ const TYPED_RULES = Rules.build((rules) => }) .typed("explicit-function-return-type", { allowExpressions: true, + allowTypedFunctionExpressions: true, + allowDirectConstAssertionInArrowFunctions: true, + allowFunctionsWithoutTypeParameters: true, allowHigherOrderFunctions: true, }) .typed("explicit-member-accessibility", { From b03faba1800c90b1f185e44b8d416a0ccbe46403 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 3 Apr 2023 16:28:23 -0700 Subject: [PATCH 19/46] Continue cleaning up resources This commit evolves the new resource API to support more signatures. It also improves the types of the use function and use method to support these improvements. This PR also continues support for resource metadata (state that lives for the entire lifetime of the resource and can be used for cross-run state). TL;DR use() takes an `IntoBlueprint` which is either a `ResourceBlueprint` or a `ResourceConstructor`. In the next commit, it will also take a function that returns a `ResourceBlueprint`, which will bring back `use(() => Counter(start))`. There are two remaining resource features needed for parity with the system before the reactive primitive reform in this PR: - Support for `use(() => Blueprint) - Some way to provide an initial value to a resource, to support frameworks (React) that can't run the resource constructor until after the first render. The second of these is tricky, because we want to avoid complicating all resources just to help this one case. That said, now that we have metadata that is provided to the constructor, perhaps you could provide the initial value as a distinguished kind of metadata. I'll have to think about it. --- packages/universal/core-utils/index.ts | 10 +- packages/universal/core-utils/src/object.ts | 81 ++++++- .../universal/interfaces/src/description.d.ts | 46 ++-- .../src/primitives}/delegate.ts | 30 +-- .../reactive/src/primitives/utils.ts | 9 + packages/universal/resource/index.ts | 7 +- packages/universal/resource/src/api.ts | 61 ++++++ .../universal/resource/src/resource-list.ts | 89 +++----- packages/universal/resource/src/resource.ts | 206 +++++++++++------- packages/universal/resource/src/types.ts | 16 +- .../universal/resource/tests/resource.spec.ts | 126 ++++++++++- packages/universal/runtime/index.ts | 6 +- .../universal/runtime/src/context/context.ts | 60 ++--- packages/universal/universal/index.ts | 3 +- .../universal/src/reactive-core/into.ts | 1 + .../universal/src/reactive-core/reactive.ts | 6 +- .../universal/src/reactive-core/service.ts | 14 +- .../{factory.spec.ts => factory.spec.todo.ts} | 36 +-- .../universal/tests/support/scenario.ts | 60 ----- 19 files changed, 536 insertions(+), 331 deletions(-) rename packages/universal/{universal/src/reactive-core => reactive/src/primitives}/delegate.ts (57%) create mode 100644 packages/universal/resource/src/api.ts rename packages/universal/universal/tests/{factory.spec.ts => factory.spec.todo.ts} (92%) delete mode 100644 packages/universal/universal/tests/support/scenario.ts diff --git a/packages/universal/core-utils/index.ts b/packages/universal/core-utils/index.ts index a9b61381..38377552 100644 --- a/packages/universal/core-utils/index.ts +++ b/packages/universal/core-utils/index.ts @@ -1,4 +1,4 @@ - export { +export { firstNItems, getFirst, getLast, @@ -25,7 +25,13 @@ export type { JsonValue, } from "./src/json.js"; export { isJSONObject, stringifyJSON } from "./src/json.js"; -export { isObject, objectHasKeys, readonly } from "./src/object.js"; +export { + getter, + isObject, + method, + objectHasKeys, + readonly, +} from "./src/object.js"; export { type Matcher, Overload, type TypedOverload } from "./src/overload.js"; export { isEmptyMatch, matchPattern, Pattern } from "./src/regexp.js"; export { diff --git a/packages/universal/core-utils/src/object.ts b/packages/universal/core-utils/src/object.ts index 8042c739..221aab3e 100644 --- a/packages/universal/core-utils/src/object.ts +++ b/packages/universal/core-utils/src/object.ts @@ -10,7 +10,7 @@ export function objectHasKeys(object: object): boolean { return isPresentArray(Object.keys(object)); } - type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; +type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; type WithReadonly = Expand< Exclude & { @@ -18,11 +18,86 @@ type WithReadonly = Expand< } >; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AnyKey = keyof any; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AnyFunction = (...args: any[]) => any; + +type DefineReadonly = Expand< + Exclude & { + readonly [P in K]: V; + } +>; + +type Define = Expand< + Exclude & { + readonly [P in keyof R]: R[P]; + } +>; + +export function method( + object: T, + key: K, + fn: T[K] & AnyFunction +): T; +export function method( + object: T, + key: K, + fn: V +): Define; +export function method(object: object, key: AnyKey, fn: AnyFunction): object { + Object.defineProperty(object, key, { + enumerable: false, + configurable: true, + writable: false, + value: fn, + }); + + return object; +} + +export function getter( + object: T, + key: K, + fn: (object: T) => T[K] +): T; +export function getter( + object: T, + key: K, + fn: (object: T) => V +): Define; +export function getter( + object: object, + key: AnyKey, + fn: (object: object) => unknown +): object { + Object.defineProperty(object, key, { + enumerable: false, + configurable: true, + get: function (this: object) { + return fn(this); + }, + }); + + return object; +} + export function readonly( object: T, key: K, ...args: [] | [T[K]] -): WithReadonly { +): WithReadonly; +export function readonly( + object: T, + key: K, + value: V +): DefineReadonly; +export function readonly( + object: object, + key: AnyKey, + ...args: [] | [unknown] +): object { if (isSingleItemArray(args)) { Object.defineProperty(object, key, { enumerable: true, @@ -36,5 +111,5 @@ export function readonly( }); } - return object as WithReadonly; + return object; } diff --git a/packages/universal/interfaces/src/description.d.ts b/packages/universal/interfaces/src/description.d.ts index 4da57de9..c763ddfe 100644 --- a/packages/universal/interfaces/src/description.d.ts +++ b/packages/universal/interfaces/src/description.d.ts @@ -45,6 +45,8 @@ export interface DescriptionDescribeOptions extends StackFrameDisplayOptions { color?: boolean | undefined; } +export type DescriptionKey = string | number; + export interface Description extends DescriptionArgs { readonly name: string; readonly fullName: string; @@ -66,37 +68,42 @@ export interface Description extends DescriptionArgs { args?: DescriptionArgument[] ) => Description; /** - * An index is an integer property access on an object. This access must refer to a stable - * cell for the lifetime of the object referred to by the parent description. + * An index is an integer property access on an object. This access must refer + * to a stable cell for the lifetime of the object referred to by the parent + * description. */ index: (index: number) => Description; /** - * A property is a string property access on an object. This access must refer to a stable - * cell for the lifetime of the object referred to by the parent description. + * A property is a string property access on an object. This access must refer + * to a stable cell for the lifetime of the object referred to by the parent + * description. */ property: (name: string) => Description; /** - * A `key` is like a property access, but the name is not a string property access. For example, - * the key passed to `.get` on a map is a key and not a property, because `.get` is not a property - * access. Unlike `detail`, a key refers to something that the user actually typed in their code. + * A `key` is like a property access, but the name is not a string property + * access. For example, the key passed to `.get` on a map is a key and not a + * property, because `.get` is not a property access. Unlike `detail`, a key + * refers to something that the user actually typed in their code. * - * If the key isn't a string, the code creating the description should convert it to a string for - * display purposes. If that process is lossy (i.e. multiple keys produce the same string), the - * code creating the description must pass an `id` option that so that the description refers to a - * stable cell backed by the key. + * If the key isn't a string or number, the code creating the description + * should convert it to a string for display purposes. If that process is + * lossy (i.e. multiple keys produce the same string), the code creating the + * description must pass an `id` option that so that the description refers to + * a stable cell backed by the key. */ key: ( - name: string, - options?: { id?: string | number; note?: string } + name: DescriptionKey, + options?: { id?: ReactiveId; note?: string } ) => Description; /** - * A detail is a representation of a *public* part of a value. Unlike `.property` or `.index`, the - * user will not have physically typed the name of the detail in the code. Unlike - * `.implementation`, a *detail* is a part of the public API of the value and can be understood by - * lay users. + * A detail is a representation of a *public* part of a value. Unlike + * `.property` or `.index`, the user will not have physically typed the name + * of the detail in the code. Unlike `.implementation`, a *detail* is a part + * of the public API of the value and can be understood by lay users. * - * If an explicit id is not passed to `.detail`, a detail's name must refer to a stable cell for - * the lifetime of the object referred to by the parent description. + * If an explicit id is not passed to `.detail`, a detail's name must refer to + * a stable cell for the lifetime of the object referred to by the parent + * description. */ detail: ( name: string, @@ -141,6 +148,7 @@ export type ValueType = | "delegate" | "static" | "cell" + | "collection" | "formula" | "resource" | "service" diff --git a/packages/universal/universal/src/reactive-core/delegate.ts b/packages/universal/reactive/src/primitives/delegate.ts similarity index 57% rename from packages/universal/universal/src/reactive-core/delegate.ts rename to packages/universal/reactive/src/primitives/delegate.ts index a409d732..4cf64c74 100644 --- a/packages/universal/universal/src/reactive-core/delegate.ts +++ b/packages/universal/reactive/src/primitives/delegate.ts @@ -1,6 +1,8 @@ +import { getter, method, readonly } from "@starbeam/core-utils"; +import type { Stack } from "@starbeam/debug"; import { callerStack, type Description } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import { TAG } from "@starbeam/runtime"; +import { TAG } from "@starbeam/shared"; import { DelegateTag, getTag, taggedDescription } from "@starbeam/tags"; export function Wrap( @@ -8,24 +10,16 @@ export function Wrap( value: T, desc?: Description | string ): T & U { - Object.defineProperty(value, TAG, { - configurable: true, - writable: true, - value: DelegateTag.create(delegateDesc(reactive, desc), [getTag(reactive)]), - }); + readonly( + value, + TAG, + DelegateTag.create(delegateDesc(reactive, desc), [getTag(reactive)]) + ); - Object.defineProperty(value, "read", { - configurable: true, - writable: true, - enumerable: false, - value: (caller = callerStack()) => reactive.read(caller), - }); - - Object.defineProperty(value, "current", { - configurable: true, - enumerable: false, - get: (caller = callerStack()) => reactive.read(caller), - }); + method(value, "read", (caller: Stack = callerStack()) => + reactive.read(caller) + ); + getter(value, "current", () => reactive.read(callerStack())); return value as T & U; } diff --git a/packages/universal/reactive/src/primitives/utils.ts b/packages/universal/reactive/src/primitives/utils.ts index 0fb52419..8ae34ff4 100644 --- a/packages/universal/reactive/src/primitives/utils.ts +++ b/packages/universal/reactive/src/primitives/utils.ts @@ -45,6 +45,15 @@ export function isFormulaFn(value: unknown): value is FormulaFn { } export function WrapFn(formula: ReactiveValue): FormulaFn { + // If the formula is *already* a function, we just need a new identity for it, + // so we'll wrap it in a simple proxy. + // + // To keep an eye on: we could also just create a new `FormulaFn` here, and if + // it's faster and/or more ergonomic to do that, we should do that. + if (typeof formula === "function") { + return new Proxy(formula, {}); + } + const fn = (): T => { return formula.read(RUNTIME.callerStack()); }; diff --git a/packages/universal/resource/index.ts b/packages/universal/resource/index.ts index 9a0d638f..b4395dcf 100644 --- a/packages/universal/resource/index.ts +++ b/packages/universal/resource/index.ts @@ -1,4 +1,3 @@ -export type { ResourceBlueprint } from "./src/resource.js"; -export { lifetime, Resource, ResourceRun, use } from "./src/resource.js"; -export { FormulaList, ResourceList } from "./src/resource-list.js"; -export type { UseMethod, UseResource } from "./src/types.js"; +export * from "./src/api.js"; +export { lifetime, type ResourceRun } from "./src/resource.js"; +export { ResourceList } from "./src/resource-list.js"; diff --git a/packages/universal/resource/src/api.ts b/packages/universal/resource/src/api.ts new file mode 100644 index 00000000..c064b4d5 --- /dev/null +++ b/packages/universal/resource/src/api.ts @@ -0,0 +1,61 @@ +import type { Description } from "@starbeam/debug"; +import type { Reactive } from "@starbeam/interfaces"; +import type { FormulaFn, ReadValue } from "@starbeam/reactive"; + +import { ResourceBlueprintImpl, type UseOptions } from "./resource.js"; +import type { ResourceConstructor } from "./types.js"; + +export type UseFnOptions = UseOptions< + M, + { + readonly description?: Description | undefined; + readonly lifetime: object; + } +>; + +/** + * The `use` function instantiates resources (it's like `new`, but for + * resources). It takes a resource blueprint or resource constructor and returns + * a resource instance. + * + * When it receives a resource constructor, it behaves as if the `use` function + * was called with a blueprint created from the constructor. + */ +export function use( + blueprint: IntoResourceBlueprint, + options: UseFnOptions +): Resource { + return ResourceBlueprintImpl.evaluate(blueprint, options, options.lifetime); +} + +declare const ResourceBrand: unique symbol; +export type Resource = FormulaFn> & { + [ResourceBrand]: true; +}; +export const Resource = ResourceBlueprintImpl.create; + +export { isResource } from "./resource.js"; + +export type ResourceBlueprint = + | ResourceBlueprintImpl + | ResourceBlueprintImpl, void>; + +export type IntoResourceBlueprint = + | ResourceBlueprint + | ResourceConstructor; + +export function IntoResourceBlueprint( + value: IntoResourceBlueprint +): ResourceBlueprint { + if (isResourceBlueprint(value)) { + return value; + } else { + return Resource(value); + } +} + +export function isResourceBlueprint( + value: unknown +): value is ResourceBlueprint { + return value instanceof ResourceBlueprintImpl; +} diff --git a/packages/universal/resource/src/resource-list.ts b/packages/universal/resource/src/resource-list.ts index 8abe3fdf..ee0dd920 100644 --- a/packages/universal/resource/src/resource-list.ts +++ b/packages/universal/resource/src/resource-list.ts @@ -1,23 +1,29 @@ -import type { Reactive, ReactiveValue } from "@starbeam/interfaces"; -import { CachedFormula, Formula, type ReadValue } from "@starbeam/reactive"; +import { Desc, type Description } from "@starbeam/debug"; import { LIFETIME } from "@starbeam/runtime"; -import { Resource, type ResourceBlueprint, use } from "./resource.js"; +import { + Resource, + type ResourceBlueprint, + use, + type UseFnOptions, +} from "./api.js"; -export function ResourceList( - list: Iterable, +export function ResourceList( + list: Iterable, { key, map, + description, }: { - key: (item: T) => unknown; - map: (item: T) => ResourceBlueprint; + key: (item: Item) => Key; + map: (item: Item) => ResourceBlueprint; + description?: string | Description; } -): ResourceBlueprint>[]> { - const resources = new ResourceMap(); +): ResourceBlueprint[], void> { + const resources = new ResourceMap(Desc("collection", description)); return Resource((_run, _metadata, lifetime) => { - const result: Resource>[] = []; + const result: Resource[] = []; const remaining = new Set(); for (const item of list) { const k = key(item); @@ -27,37 +33,43 @@ export function ResourceList( if (resource) { result.push(resource); } else { - result.push(resources.create(k, map(item), lifetime)); + result.push(resources.create(k, map(item), { lifetime })); } } resources.update(remaining); return result; - }); + }) as ResourceBlueprint[]>; } -type InternalMap = Map< - unknown, - { resource: Resource>; lifetime: object } ->; +type Key = string | number | { key: unknown; description: string | number }; +type InternalMap = Map; lifetime: object }>; -class ResourceMap { - readonly #map: InternalMap = new Map(); +class ResourceMap { + readonly #map: InternalMap = new Map(); + readonly #description: Description; - get(key: unknown): Resource> | undefined { + constructor(description: Description) { + this.#description = description; + } + + get(key: unknown): Resource | undefined { return this.#map.get(key)?.resource; } create( - key: unknown, - resource: ResourceBlueprint, - parentLifetime: object - ): Resource> { + key: Key, + resource: ResourceBlueprint, + options: UseFnOptions + // parentLifetime: object + ): Resource { const lifetime = {}; - LIFETIME.link(parentLifetime, lifetime); + LIFETIME.link(options.lifetime, lifetime); const newResource = use(resource, { lifetime, + metadata: options.metadata, + description: this.#description.key(String(key)), }); this.#map.set(key, { resource: newResource, lifetime }); return newResource; @@ -76,32 +88,3 @@ class ResourceMap { } } } - -export function FormulaList( - list: Iterable, - { - key, - map, - }: { - key: (item: T) => unknown; - map: (item: T) => U; - } -): Reactive { - const prev = new Map>(); - - return Formula(() => { - const result: U[] = []; - for (const item of list) { - const k = key(item); - const r = prev.get(k); - if (r) { - result.push(r.read()); - } else { - const newR = CachedFormula(() => map(item)); - result.push(newR.current); - prev.set(k, newR); - } - } - return result; - }); -} diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index c2dd3041..1a69081e 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -1,20 +1,11 @@ import { Desc, DisplayStruct } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; -import { - CachedFormula, - type FormulaFn, - isFormulaFn, - read, - type ReadValue, -} from "@starbeam/reactive"; +import { CachedFormula, read, type ReadValue } from "@starbeam/reactive"; import { LIFETIME, TAG } from "@starbeam/runtime"; -import type { - ResourceCleanup, - ResourceConstructor, - UseMethod, - UseResource, -} from "./types.js"; +import type { IntoResourceBlueprint, Resource } from "./api.js"; +import { isResourceBlueprint, type ResourceBlueprint } from "./api.js"; +import { type ResourceCleanup, type ResourceConstructor } from "./types.js"; /** * `ResourceRun` is passed in to the user-specified `ResourceConstructor` @@ -25,14 +16,11 @@ import type { export class ResourceRun { readonly #state: ResourceState; - constructor(state: ResourceOptions) { - this.#state = { - metadata: undefined, - ...state, - } as ResourceState; + constructor(state: ResourceState) { + this.#state = state; } - on = { + readonly on = { /** * on.cleanup happens once for each run of the resource. */ @@ -54,40 +42,36 @@ export class ResourceRun { }, }; - use = (( - resource: UseResource, - metadata?: unknown - ): FormulaFn => - use(resource, { metadata, lifetime: this })) as UseMethod; + use = ( + resource: IntoResourceBlueprint, + ...options: UseArgs + ): Resource => { + return ResourceBlueprintImpl.evaluate(resource, options[0] ?? {}, this); + }; } -/** - * A blueprint is a reactive object that evaluates to the current - * resource run for a given resource constructor. - */ -export function use( - resource: UseResource, - options: ResourceOptions -): Resource> { - if (isFormulaFn(resource)) { - return resource as Resource>; - } else if (typeof resource === "function") { - return useResourceConstructor(resource, options); - } else { - return useResourceConstructor( - ResourceBlueprint.Constructor(resource), - options - ); - } -} +type UseArgs = M extends void + ? [options?: UseOptions] + : [options: UseOptions]; -export type ResourceOptions = M extends void - ? Omit, "metadata"> & { - readonly metadata?: undefined; - } - : ResourceState; +export type ResourceFor = + R extends ResourceConstructor | ResourceBlueprint + ? Resource + : never; -interface ResourceState { +export type ResourceStateFor< + R extends ResourceConstructor | ResourceBlueprint +> = R extends + | ResourceConstructor + | ResourceBlueprint + ? ResourceState + : never; + +export type UseOptions = M extends void + ? Defaults & { readonly metadata?: void } + : Defaults & { readonly metadata: M }; + +export interface ResourceState { /** * A resource's metadata persists across runs of the resource. */ @@ -98,65 +82,119 @@ interface ResourceState { * parent is contained inside the root. */ readonly lifetime: object; -} -// export interface ResourceBlueprint { -// metadata: (metadata: M) => ResourceBlueprint; -// } + readonly description: Description; +} -export type Resource = FormulaFn; +export interface ResourceBlueprintParts { + readonly Constructor: ResourceConstructor; + readonly metadata: M; + readonly description: Description; +} -export class ResourceBlueprint { +export class ResourceBlueprintImpl { static create( this: void, resource: ResourceConstructor, description?: string | Description - ): ResourceBlueprint, M> { - return new ResourceBlueprint( - resource, + ): ResourceBlueprint { + return new ResourceBlueprintImpl( + resource as ResourceConstructor, + undefined, Desc("resource", description) - ) as ResourceBlueprint, M>; + ); } - static Constructor( - blueprint: ResourceBlueprint - ): ResourceConstructor { - return blueprint.#Constructor; + static from( + value: IntoResourceBlueprint + ): ResourceBlueprint { + return isResourceBlueprint(value) + ? value + : ResourceBlueprintImpl.create(value); } - #Constructor: ResourceConstructor; + static evaluate( + intoBlueprint: IntoResourceBlueprint, + options: { + metadata?: M | undefined | void; + description?: Description | undefined; + }, + lifetime: object + ): Resource { + const blueprint = ResourceBlueprintImpl.from(intoBlueprint); + const Constructor = blueprint.#Constructor as ResourceConstructor; + const metadata = options.metadata ?? (blueprint.#metadata as M); + const description = options.description ?? blueprint.#description; + + if (lifetime === undefined) { + console.trace({ blueprint, options, lifetime }); + } + + return evaluateResourceConstructor( + { + Constructor, + metadata, + description, + }, + lifetime + ); + } + + #Constructor: ResourceConstructor; + #metadata: unknown; #description: Description; - constructor(construct: ResourceConstructor, description: Description) { - this.#Constructor = construct; + constructor( + Constructor: ResourceConstructor, + metadata: unknown, + description: Description + ) { + this.#Constructor = Constructor; + this.#metadata = metadata; this.#description = description; } metadata(metadata: M): ResourceBlueprint { - return Resource((run, _, lifetime) => - this.#Constructor(run as ResourceRun, metadata, lifetime) - ) as ResourceBlueprint; + return new ResourceBlueprintImpl( + this.#Constructor, + metadata, + this.#description + ) as unknown as ResourceBlueprint; } } -export const Resource = ResourceBlueprint.create; - const RESOURCE_LIFETIMES = new WeakMap, object>(); export function lifetime(resource: Resource): object { return RESOURCE_LIFETIMES.get(resource) as object; } -function useResourceConstructor( - resource: ResourceConstructor, - options: ResourceOptions -): Resource> { +export function isResource(value: unknown): value is Resource { + return RESOURCE_LIFETIMES.has(value as Resource); +} + +/** + * Evaluate a resource constructor, returning a resource instance. This function + * is the workhorse of the resource system. It handles creating resource runs, + * finalizing previous runs, and linking lifetimes. + */ +export function evaluateResourceConstructor( + blueprint: ResourceBlueprintParts, + lifetime: object +): Resource { let last: ResourceRun | undefined; const formula = CachedFormula(() => { - const next = new ResourceRun(options); + const { Constructor, metadata, description } = blueprint; + + const state = { + metadata, + description, + lifetime, + }; + const next = new ResourceRun(state); - LIFETIME.link(options.lifetime, next); - const instance = resource(next, options.metadata as M, options.lifetime); + LIFETIME.link(lifetime, next); + const instance = Constructor(next, metadata, lifetime); // Finalize the previous run after running the new one to give the new one a // chance to adopt resources from the previous run. @@ -177,9 +215,15 @@ function useResourceConstructor( }); } - const instance = CachedFormula(() => read(formula.current) as ReadValue); + // Declare that this formula is a `Resource`, which gives it a non-existent + // symbol key. + const resource = CachedFormula( + () => read(formula.current) as ReadValue + ) as Resource; - RESOURCE_LIFETIMES.set(instance, options.lifetime); + // Associate the resource with its lifetime in a WeakMap. _Dynamic_ checks for + // whether a value is a resource will use this WeakMap. + RESOURCE_LIFETIMES.set(resource, lifetime); - return instance; + return resource; } diff --git a/packages/universal/resource/src/types.ts b/packages/universal/resource/src/types.ts index fde71df4..224d822d 100644 --- a/packages/universal/resource/src/types.ts +++ b/packages/universal/resource/src/types.ts @@ -1,20 +1,16 @@ -import type { FormulaFn } from "@starbeam/reactive"; +import type { Reactive } from "@starbeam/interfaces"; -import type { Resource, ResourceBlueprint, ResourceRun } from "./resource.js"; +import type { ResourceRun } from "./resource.js"; -export type UseResource = - | ResourceBlueprint - | ResourceConstructor - | Resource; - -export type UseMethod = ((resource: UseResource) => FormulaFn) & - ((resource: UseResource, metadata: M) => FormulaFn); +export type ResourceConstructor = + | SpecificResourceConstructor + | SpecificResourceConstructor, M>; /** * A resource constructor is a user-defined function that runs for each resource * run. */ -export type ResourceConstructor = ( +export type SpecificResourceConstructor = ( run: ResourceRun, /** * The `resource` parameter provides information about the entire resource diff --git a/packages/universal/resource/tests/resource.spec.ts b/packages/universal/resource/tests/resource.spec.ts index e62c6112..7d4c627d 100644 --- a/packages/universal/resource/tests/resource.spec.ts +++ b/packages/universal/resource/tests/resource.spec.ts @@ -170,28 +170,142 @@ describe("resources", () => { ); }); - test("adopting resources", () => { + test.todo("inner use() returning a blueprint", () => { + const name = Cell("default"); + let connectedCount = 0; + function Socket(name: Cell) { + return Resource(({ on }) => { + const connected = { + socketName: name.current as string | null, + connected: ++connectedCount, + }; + + on.cleanup(() => { + connected.socketName = null; + }); + + return connected; + }); + } + + const Channel = Resource(({ use }) => { + const socket = use(() => Socket(name)); + const messages = Cell(0); + + return { + get description() { + const { connected, socketName } = socket.current; + return `${ + socketName ?? "disconnected" + } (connected: ${connected}, messages: ${messages.current})`; + }, + get socket() { + return socket.current; + }, + get messages() { + return messages.current; + }, + send() { + messages.current++; + }, + }; + }); + + const lifetime = {}; + const channel = use(Channel, { lifetime }); + + expect(channel.current.description).toBe( + "default (connected: 1, messages: 0)" + ); + + channel.current.send(); + expect(channel.current.description).toBe( + "default (connected: 1, messages: 1)" + ); + + name.set("socketa"); + expect(channel.current.description).toBe( + "socketa (connected: 2, messages: 1)" + ); + }); + + test("inline child resources", () => { + const name = Cell("default"); + let connectedCount = 0; + + const Channel = Resource(({ use }) => { + const socket = use(({ on }) => { + const connected = { + socketName: name.current as string | null, + connected: ++connectedCount, + }; + + on.cleanup(() => { + connected.socketName = null; + }); + + return connected; + }); + const messages = Cell(0); + + return { + get description() { + const { connected, socketName } = socket.current; + return `${ + socketName ?? "disconnected" + } (connected: ${connected}, messages: ${messages.current})`; + }, + get socket() { + return socket.current; + }, + get messages() { + return messages.current; + }, + send() { + messages.current++; + }, + }; + }); + + const lifetime = {}; + const channel = use(Channel, { lifetime }); + + expect(channel.current.description).toBe( + "default (connected: 1, messages: 0)" + ); + + channel.current.send(); + expect(channel.current.description).toBe( + "default (connected: 1, messages: 1)" + ); + + name.set("socketa"); + expect(channel.current.description).toBe( + "socketa (connected: 2, messages: 1)" + ); + }); + + test("external resources", () => { const childResource = new TestResource(); const child = childResource.instance; const invalidateParent = Marker(); - const Parent = Resource(({ use }, meta: { initHere: number }) => { - const resource = use(child); + const Parent = Resource((_, meta: { initHere: number }) => { invalidateParent.read(); meta.initHere++; return { get state() { return { - child: resource.current.state, + child: child.current.state, parent: { init: meta.initHere, }, }; }, increment() { - resource.current.increment(); + child.current.increment(); }, }; }); @@ -306,7 +420,7 @@ interface TestInstance { class TestResource { readonly #lifetime: object; readonly #marker: Marker; - readonly #blueprint: ResourceBlueprint; + readonly #blueprint: ResourceBlueprint; readonly #instance: Resource; constructor() { diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index cc61d93c..15063e4e 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -1,8 +1,4 @@ -export { - type ComponentContext, - CONTEXT, - type Context, -} from "./src/context/context.js"; +export { type AppContext, CONTEXT } from "./src/context/context.js"; export { type CleanupTarget, LIFETIME, diff --git a/packages/universal/runtime/src/context/context.ts b/packages/universal/runtime/src/context/context.ts index 25c22264..4faabb86 100644 --- a/packages/universal/runtime/src/context/context.ts +++ b/packages/universal/runtime/src/context/context.ts @@ -1,8 +1,18 @@ -import { getLast, isPresentArray } from "@starbeam/core-utils"; - -export class Context { - readonly component = new ComponentContext(); - +/** + * An `AppContext` represents the context of a single "application" for a given + * renderer. + * + * An application is a user-space concept that represents a root component and + * the components that it renders. Its primary purpose is to facilitate + * services: resources whose lifetime is scoped to the application. + * + * Services avoid using module state for app-wide concerns, which makes it + * possible to have multiple instances of the same service in multiple apps on + * the same page. This supports efficient acceptance testing and server-side + * rendering, because it makes it possible to evaluate an app's *code* once and + * then *instantiate* it multiple times. + */ +export class AppContext { #app: object | undefined; #singletons = new WeakMap(); @@ -68,42 +78,4 @@ class SingletonContext { } } -export class ComponentContext { - readonly #stack: object[] = []; - readonly #singleton = new SingletonContext(); - - get current(): object { - const current = this.#current; - if (current === undefined) { - throw Error( - "You are attempting to use a feature of Starbeam that depends on the current component, but no component is currently active." - ); - } - return current; - } - - get #current(): object | undefined { - return getLast(this.#stack); - } - - push(component: object): void { - this.#stack.push(component); - } - - pop(): void { - this.#stack.pop(); - } - - exists(): boolean { - return isPresentArray(this.#stack); - } - - create( - constructor: (...args: Args) => Ret, - ...args: Args - ): Ret { - return this.#singleton.create(this.#current, constructor, ...args); - } -} - -export const CONTEXT = new Context(); +export const CONTEXT = new AppContext(); diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 95aab6c8..a5d3d0f8 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -4,9 +4,7 @@ export { CustomBlueprint, CustomBuilder, } from "./src/reactive-core/custom.js"; -export { Wrap } from "./src/reactive-core/delegate.js"; export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; -export { Freshness } from "./src/reactive-core/higher-level/freshness.js"; export { Factory, type IntoReactiveObject, @@ -40,6 +38,7 @@ export { Formula as PolledFormula, Static, } from "@starbeam/reactive"; +export { Wrap } from "@starbeam/reactive/src/primitives/delegate.js"; export { Resource, type ResourceBlueprint, diff --git a/packages/universal/universal/src/reactive-core/into.ts b/packages/universal/universal/src/reactive-core/into.ts index 7867911f..bb207105 100644 --- a/packages/universal/universal/src/reactive-core/into.ts +++ b/packages/universal/universal/src/reactive-core/into.ts @@ -26,6 +26,7 @@ export function IntoResource>( export type Factory = Blueprint | ReactiveFactory; + export const Factory = { create: createReactiveObject, initial, diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index 94d073ff..5faccc73 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -52,6 +52,10 @@ export class ReactiveBlueprint { } } +export function create(blueprint: ReactiveBlueprint): T { + return blueprint.create(); +} + function construct(constructor: ReactiveFactory): T | Reactive { try { return (constructor as () => T | Reactive)(); @@ -60,4 +64,4 @@ function construct(constructor: ReactiveFactory): T | Reactive { } } -export type Blueprint = ResourceBlueprint | ReactiveBlueprint; +export type Blueprint = ResourceBlueprint; diff --git a/packages/universal/universal/src/reactive-core/service.ts b/packages/universal/universal/src/reactive-core/service.ts index 5c3b93ce..74f5bdce 100644 --- a/packages/universal/universal/src/reactive-core/service.ts +++ b/packages/universal/universal/src/reactive-core/service.ts @@ -1,16 +1,20 @@ import { Desc } from "@starbeam/debug"; import type { Description, Reactive } from "@starbeam/interfaces"; -import type { ResourceBlueprint } from "@starbeam/resource"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; import { CONTEXT } from "@starbeam/runtime"; import { Factory, type IntoResource } from "./into.js"; -import type { Blueprint } from "./reactive.js"; +import { type Blueprint } from "./reactive.js"; export function Service( - create: Blueprint, + blueprint: Blueprint, description?: string | Description -): ServiceBlueprint { - return new ServiceBlueprint(create, Desc("blueprint:service", description)); +): ResourceBlueprint | ResourceBlueprint> { + return Resource(({ use }) => { + return CONTEXT.create(blueprint, () => { + return use(blueprint); + }); + }, Desc("blueprint:service", description).detail("service")); } Service.create = ( diff --git a/packages/universal/universal/tests/factory.spec.ts b/packages/universal/universal/tests/factory.spec.todo.ts similarity index 92% rename from packages/universal/universal/tests/factory.spec.ts rename to packages/universal/universal/tests/factory.spec.todo.ts index c7442c38..28345d63 100644 --- a/packages/universal/universal/tests/factory.spec.ts +++ b/packages/universal/universal/tests/factory.spec.todo.ts @@ -211,21 +211,21 @@ interface Context { readonly value: Validation; } -function TrackingContext(callback: () => T): Context { - const formula = FormulaValidation(callback); - - return { - get value(): Validation { - const status = formula.frame.validate(); - - if (status.status === "valid") { - return status; - } else { - return { - status: "stale", - value: Frame.value(formula.poll()), - }; - } - }, - }; -} +// function TrackingContext(callback: () => T): Context { +// const formula = FormulaValidation(callback); + +// return { +// get value(): Validation { +// const status = formula.frame.validate(); + +// if (status.status === "valid") { +// return status; +// } else { +// return { +// status: "stale", +// value: Frame.value(formula.poll()), +// }; +// } +// }, +// }; +// } diff --git a/packages/universal/universal/tests/support/scenario.ts b/packages/universal/universal/tests/support/scenario.ts deleted file mode 100644 index 0b70610e..00000000 --- a/packages/universal/universal/tests/support/scenario.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { describe, test } from "@starbeam-workspace/test-utils"; -import type { Awaitable } from "vitest"; - -export function scenario( - description: string, - setup: () => Awaitable -): Scenario { - const s = new Scenario(setup); - queueMicrotask(() => { - Scenario.finalize(s, description); - }); - return s; -} - -type TestFn = (value: T) => Awaitable<(() => Awaitable)[] | undefined>; - -interface TestDefinition { - description: string; - fn: TestFn; -} - -class Scenario { - static finalize(s: Scenario, description: string): void { - describe(description, () => { - for (const definition of s.#definitions) { - test(definition.description, async () => { - const value = await s.#setup(); - const more = (await definition.fn(value)) ?? []; - - const [first, ...rest] = more; - - if (first) { - await first(); - } - - for (let i = 0; i < rest.length; i++) { - const result = await s.#setup(); - const newMore = (await definition.fn( - result - )) as (() => Awaitable)[]; - const next = newMore[i + 1] as () => Awaitable; - await next(); - } - }); - } - }); - } - - readonly #setup: () => Awaitable; - readonly #definitions: TestDefinition[] = []; - - constructor(setup: () => Awaitable) { - this.#setup = setup; - } - - test(description: string, fn: TestFn): this { - this.#definitions.push({ description, fn }); - return this; - } -} From 19c10bddc8fc11e2c1983f0689619b2077ca6b9e Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 3 Apr 2023 09:19:08 -0700 Subject: [PATCH 20/46] Added support for use(() => Blueprint) --- packages/universal/resource/src/resource.ts | 19 ++++++ packages/universal/resource/src/types.ts | 10 ++-- .../universal/resource/tests/resource.spec.ts | 59 ++++++++++++++++++- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index 1a69081e..780c0035 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -113,6 +113,21 @@ export class ResourceBlueprintImpl { : ResourceBlueprintImpl.create(value); } + static run( + this: void, + blueprint: ResourceBlueprint, + run: ResourceRun, + lifetime: object + ): Resource { + let instance = blueprint.#Constructor(run, {}, lifetime); + + while (isResourceBlueprint(instance)) { + instance = ResourceBlueprintImpl.evaluate(instance, {}, lifetime); + } + + return instance as Resource; + } + static evaluate( intoBlueprint: IntoResourceBlueprint, options: { @@ -196,6 +211,10 @@ export function evaluateResourceConstructor( LIFETIME.link(lifetime, next); const instance = Constructor(next, metadata, lifetime); + if (isResourceBlueprint(instance)) { + return ResourceBlueprintImpl.run(instance, next, lifetime); + } + // Finalize the previous run after running the new one to give the new one a // chance to adopt resources from the previous run. if (last !== undefined) LIFETIME.finalize(last); diff --git a/packages/universal/resource/src/types.ts b/packages/universal/resource/src/types.ts index 224d822d..8e77ddff 100644 --- a/packages/universal/resource/src/types.ts +++ b/packages/universal/resource/src/types.ts @@ -1,10 +1,12 @@ import type { Reactive } from "@starbeam/interfaces"; +import type { ResourceBlueprint } from "./api.js"; import type { ResourceRun } from "./resource.js"; export type ResourceConstructor = - | SpecificResourceConstructor - | SpecificResourceConstructor, M>; + | SpecificResourceConstructor, M> + | SpecificResourceConstructor, M> + | SpecificResourceConstructor; /** * A resource constructor is a user-defined function that runs for each resource @@ -13,13 +15,13 @@ export type ResourceConstructor = export type SpecificResourceConstructor = ( run: ResourceRun, /** - * The `resource` parameter provides information about the entire resource + * The `metadata` parameter provides information about the entire resource * that persists across runs. It is useful when reusing state across runs. The * `lifetime` property makes it possible to link state to the entire lifetime * of the resource, which ensures that it it will get cleaned up, at the * latest, when the resource itself is finalized. */ - resource: M, + metadata: M, /** * The `lifetime` parameter is the lifetime of the entire resource. diff --git a/packages/universal/resource/tests/resource.spec.ts b/packages/universal/resource/tests/resource.spec.ts index 7d4c627d..e04a7190 100644 --- a/packages/universal/resource/tests/resource.spec.ts +++ b/packages/universal/resource/tests/resource.spec.ts @@ -170,7 +170,64 @@ describe("resources", () => { ); }); - test.todo("inner use() returning a blueprint", () => { + test("inner use() consuming reactive state and returning a blueprint", () => { + const salutation = Cell("Mr."); + const invalidateOuter = Marker(); + const counts = { + inner: 0, + outer: 0, + }; + + function Greeting(name: Cell) { + return Resource(({ use }) => { + counts.outer++; + invalidateOuter.read(); + + const sal = use(() => { + counts.inner++; + return salutation.current; + }); + + return CachedFormula(() => `${sal.current} ${name.current}`); + }); + } + + const name = Cell("Person"); + + const lifetime = {}; + const greeting = use(Greeting(name), { lifetime }); + + expect(greeting.current).toBe("Mr. Person"); + expect(counts).toEqual({ inner: 1, outer: 1 }); + + name.current = "Persona"; + expect(greeting.current).toBe("Mr. Persona"); + expect(counts).toEqual({ inner: 1, outer: 1 }); + + salutation.current = "Mx."; + expect(greeting.current).toBe("Mx. Persona"); + // The outer resource *constructor* does not have a dependency on the + // inner resource, since the outer resource doesn't read the value of the + // inner resource during construction. The outer resource *value*, on the + // other hand, does depend on the inner resource, so re-evaluating + // `greeting` causes the inner resource to be re-initialized. + // + // You can see that this is the correct behavior by observing that the only + // way to directly check whether the `salutation` cell was reflected + // correctly is by checking the value of the `greeting` resource, which is + // the exact check that caused the inner resource to be re-initialized. + expect(counts).toEqual({ inner: 2, outer: 1 }); + + invalidateOuter.mark(); + expect(greeting.current).toBe("Mx. Persona"); + expect(counts).toEqual({ inner: 3, outer: 2 }); + + name.current = "Persone"; + expect(greeting.current).toBe("Mx. Persone"); + expect(counts).toEqual({ inner: 3, outer: 2 }); + }); + + test("inner use() returning a blueprint", () => { const name = Cell("default"); let connectedCount = 0; function Socket(name: Cell) { From 3d831925373a8a59130cfccc0ad8c19e45e2dec6 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 3 Apr 2023 11:43:38 -0700 Subject: [PATCH 21/46] @starbeam/service --- packages/universal/resource/package.json | 3 + .../universal/resource/tests/package.json | 7 +- packages/universal/service/.eslintrc.json | 12 + packages/universal/service/.npmrc | 2 + packages/universal/service/README.md | 293 +++++++++++ packages/universal/service/index.ts | 1 + packages/universal/service/package.json | 36 ++ packages/universal/service/rollup.config.mjs | 3 + packages/universal/service/src/service.ts | 26 + .../universal/service/tests/.eslintrc.json | 12 + packages/universal/service/tests/.npmrc | 2 + packages/universal/service/tests/package.json | 22 + .../universal/service/tests/service.spec.ts | 42 ++ .../universal/service/tests/tsconfig.json | 13 + packages/universal/service/tsconfig.json | 12 + packages/universal/universal/index.ts | 8 - .../universal/src/reactive-core/reactive.ts | 2 +- .../universal/src/reactive-core/service.ts | 64 --- pnpm-lock.yaml | 492 +++++------------- 19 files changed, 601 insertions(+), 451 deletions(-) create mode 100644 packages/universal/service/.eslintrc.json create mode 100644 packages/universal/service/.npmrc create mode 100644 packages/universal/service/README.md create mode 100644 packages/universal/service/index.ts create mode 100644 packages/universal/service/package.json create mode 100644 packages/universal/service/rollup.config.mjs create mode 100644 packages/universal/service/src/service.ts create mode 100644 packages/universal/service/tests/.eslintrc.json create mode 100644 packages/universal/service/tests/.npmrc create mode 100644 packages/universal/service/tests/package.json create mode 100644 packages/universal/service/tests/service.spec.ts create mode 100644 packages/universal/service/tests/tsconfig.json create mode 100644 packages/universal/service/tsconfig.json delete mode 100644 packages/universal/universal/src/reactive-core/service.ts diff --git a/packages/universal/resource/package.json b/packages/universal/resource/package.json index d74e2bef..6d370d6c 100644 --- a/packages/universal/resource/package.json +++ b/packages/universal/resource/package.json @@ -2,6 +2,9 @@ "name": "@starbeam/resource", "main": "index.ts", "types": "index.ts", + "exports": { + "default": "./index.ts" + }, "publishConfig": { "exports": { ".": { diff --git a/packages/universal/resource/tests/package.json b/packages/universal/resource/tests/package.json index 122e8439..6af01b72 100644 --- a/packages/universal/resource/tests/package.json +++ b/packages/universal/resource/tests/package.json @@ -5,16 +5,17 @@ "type": "module", "starbeam:type": "tests", "scripts": { - "test:lint": "eslint" + "test:lint": "eslint", + "test:types": "tsc -b" }, "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/js": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^", "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", - "@starbeam/shared": "workspace:^", - "@starbeam-workspace/test-utils": "workspace:^" + "@starbeam/shared": "workspace:^" } } diff --git a/packages/universal/service/.eslintrc.json b/packages/universal/service/.eslintrc.json new file mode 100644 index 00000000..ca858e44 --- /dev/null +++ b/packages/universal/service/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/commonjs"], + "files": ["index.ts", "src/**/*.ts"], + "parserOptions": { + "project": "packages/universal/service/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/service/.npmrc b/packages/universal/service/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/service/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/service/README.md b/packages/universal/service/README.md new file mode 100644 index 00000000..673ed872 --- /dev/null +++ b/packages/universal/service/README.md @@ -0,0 +1,293 @@ +# Resources + +A resource is a reactive constructor function with support for cleanup. + +```ts +import { Resource, use } from "@starbeam/resource"; +import { LIFETIME } from "@starbeam/runtime"; + +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return Formula(() => { + return new Intl.DateTimeFormat().format(now.current); + }); +}); + +const lifetime = {}; +const stopwatch = use(Stopwatch, { within: lifetime }); + +// later, when the lifetime is finalized... +LIFETIME.finalize(lifetime); +// the timer is cleared and `stopwatch` will stop updating +``` + +The `Resource` function takes a _resource constructor_ function and returns a +_resource blueprint_. A resource blueprint is instantiated with a _lifetime_ and +returns a _resource instance_. + +The resource constructor function is called with a _resource run_ object that +allows the resource constructor to register cleanup functions and create child +resources. + +The return value of the resource constructor is called the resource's _instance +value_. + +In this case, the resource instance (`stopwatch`) is a reactive value that +evaluates to the current time, formatted using `Intl.DateTimeFormat`. + +## Terms + +
    +
    resource blueprint
    +
    The resource blueprint is instantiated with the `use` function and returns a resource instance
    +
    resource instance
    +
    An instance of a resource blueprint is called its resource instance.
    +
    instance value
    +
    The value returned by the resource constructor is called the instance value.
    +
    resource constructor
    +
    The function passed to the Resource function is called the resource constructor.
    +
    resource run
    +
    Each time the resource constructor runs for a given resource instance, it is called a resource run. The constructor is called with an instance of the resource run, which allows the constructor to register cleanup functions and create child resources.
    +
    + +## Assimilation + +A resource instance is always a stable reactive value. Its current value is the +most recent return value of its resource constructor. + +If a resource constructor returns a reactive value, the resource instance will +_assimilate_ that value. This means that the evaluated value of the resource +instance will be the same as the evaluated value of the returned reactive value. + +```ts +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return Formula(() => { + return new Intl.DateTimeFormat().format(now.current); + }); +}); +``` + +In this case, the _resource run_ has no reactive dependencies, but the +_instance value_ is a formulaa that depends on the `now` cell. + +This means that instances of `Stopwatch` will be reactive values that evaluate +to the current time, formatted using `Intl.DateTimeFormat`, but the resource +constructor will only be evaluated once. + +### Regular Formulas Wouldn't Work + +Let's see what would happen if you tried to model this as a single formula: + +```ts +const now = Cell(Date.now()); +let timer: number; + +const Stopwatch = Formula(() => { + if (timer) clearInterval(timer); + + timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + return new Intl.DateTimeFormat().format(now.current); +}); +``` + +Since the code that sets up the interval and the code that uses it is inside the +same formula, the formula invalidates every time the interval ticks, and the +interval will be cleaned up and recreated on every tick. Definitely not what we +wanted! + +## Resource Metadata + +In addition to state that's associated with each resource run, a resource can +have metadata that is shared across all resource runs. + +```ts +interface CounterMetadata { + interval: Reactive; + count: number; +} + +const Counter = Resource(({ on }, { metadata }: CounterMetadata)) => { + const count = Cell(metadata.count); + + const interval = setInterval(() => { + count.set(++metadata.count); + }, metadata.interval.current); + + on.cleanup(() => { + clearInterval(interval); + }); + + return count; +}; +``` + +When a resource has metadata, the initial value of the metadata is passed to the +`use` function as the second argument: + +```ts +const interval = Cell(1000); +const counter = use(Counter, { + within: lifetime, + metadata: { + interval, + count: 0, + }, +}); +``` + +Now, whenever the `interval` cell changes, the resource constructor will be +re-evaluated, but the `count` will be preserved. + +> In general, it's a good idea to avoid trying to maintain state across resource +> runs. It's sometimes necessary, but it maakes it possible to create resources +> with incoherent values, so you should try to think of an alternative if +> possible. + +## Semantics Summary + +1. A resource blueprint is instantiated with a _lifetime_ and returns a + _resource instance_. +2. When a resource run is evaluated: + 1. The previous resource run, if it exists, is finalized. + 2. Its constructor is evaluated as a formula, and its dependencies are the + dependencies of that formula. +3. When a resource instance's lifetime is finalized: + 1. Its current resource run is finalized. + 2. Any instance finalizers are run. +4. Whenever a resource instance is evaluated (i.e. its value is read): + 1. Its current resource run is validated. + 1. If it is invalid, a new resource run is created and the resource's + constructor is evaluated. + 2. If the instance value is a reactive value, the resource instance + is evaluated to the current value of that reactive value. + +### Instance Value + +While assimilation is often useful, a resource's instance value does not +**need** to be a reactive value. For example, it could be an instance of an +object that stores a cell and exposes reactive getters: + +```ts +const Stopwatch = Resource(({ on }) => { + const now = Cell(Date.now()); + + const timer = setInterval(() => { + now.set(Date.now()); + }, 1000); + + on.cleanup(() => { + clearInterval(timer); + }); + + return { + get now() { + return new Intl.DateTimeFormat().format(now.current); + }, + }; +}); +``` + +Instances of `Stopwatch` are methods with a reactive `now` property which will +change when the interval ticks. + +## Resource Runs in More Detail + +A resource _instance_ is a long-lived reactive value that exists until the +resource is finalized. A resource instance has a number of _resource runs_ over +its lifetime. + +A resource is a reactive value that evaluates to its _current value_. + +### Evaluating the Constructor + +The steps for evaluating the constructor are: + +1. Evaluate the resource's constructor formula. Evaluating the formula: + + 1. Collects the run's reactive dependencies. + 2. Collects a list of the run's cleanup functions. + 3. Links any resources created within the run to the run's lifetime. If the + same resource instance was used in a previous run, this _adopts_ the + resource. + +2. Run finalizers for the previous resource run. + 1. Run its cleanup functions. + 2. Finalize any child resources that were not adopted by the new run. + +## Evaluating a Resource + +A resource's dependencies are the combination of: + +- The dependencies of the resource's instance formula. +- The dependencies of the current resource run (its constructor). + +This means that a resource will invalidate if its instance formula invalidates +_or_ if its constructor invalidates. + +Evaluating a resource: + +1. Validate the resource run. If the resource run is invalid, [evaluate the + constructor](#evaluating-the-constructor). +2. Evaluate the resource's instance formula. + +## Composing Resources + +The `use` method makes it possible for a resource to instantiate other +resources within the lifetime of the parent resource. + +There are several aspects of the design that make it easier to compose +resources. + +### Creating a Child Resource With `use` + +```ts +const Channel = Resource(({ use }) => { + const socket = use(Socket); +}); +``` + +In this case, the Socket constructor is evaluated during `Channel`'s +constructor, and its instance is linked to the current run. Whenever the current +run is finalized, the Socket instance is finalized as well. + +This `use` works just like the imported `use` function, except that you don't +specify a lifetime. Instead, the lifetime is the current resource run. + +### Reusing a Resource + +```ts +const socket = use(Socket, { within: owner }); + +const Channel = Resource(({ use }) => { + const socket = use(socket); +}); +``` + +In this case, `socket`'s lifetime is linked to the current run. Whenever the +current run is finalized, the Socket instance is finalized as well _unless_ it +was adopted by the next run. + +> `ResourceList` uses this feature to dynamically create child resources that are +> automatically cleaned up when they aren't used anymore. diff --git a/packages/universal/service/index.ts b/packages/universal/service/index.ts new file mode 100644 index 00000000..37cd3b52 --- /dev/null +++ b/packages/universal/service/index.ts @@ -0,0 +1 @@ +export { Service, service } from "./src/service.js"; diff --git a/packages/universal/service/package.json b/packages/universal/service/package.json new file mode 100644 index 00000000..aaa64abf --- /dev/null +++ b/packages/universal/service/package.json @@ -0,0 +1,36 @@ +{ + "name": "@starbeam/service", + "main": "index.ts", + "types": "index.ts", + "exports": { + "default": "./index.ts" + }, + "publishConfig": { + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.cjs" + } + }, + "main": "dist/index.cjs", + "types": "dist/index.d.ts" + }, + "starbeam:type": "library:public", + "scripts": { + "test:specs": "vitest --run", + "test:types": "tsc -b" + }, + "dependencies": { + "@starbeam/core-utils": "workspace:^", + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", + "@starbeam/runtime": "workspace:^", + "@starbeam/shared": "workspace:^" + }, + "devDependencies": { + "@starbeam-dev/build-support": "workspace:*" + } +} diff --git a/packages/universal/service/rollup.config.mjs b/packages/universal/service/rollup.config.mjs new file mode 100644 index 00000000..dc01dc49 --- /dev/null +++ b/packages/universal/service/rollup.config.mjs @@ -0,0 +1,3 @@ +import { Package } from "@starbeam-dev/build-support"; + +export default Package.config(import.meta); diff --git a/packages/universal/service/src/service.ts b/packages/universal/service/src/service.ts new file mode 100644 index 00000000..b6338547 --- /dev/null +++ b/packages/universal/service/src/service.ts @@ -0,0 +1,26 @@ +import { Desc } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; +import { Resource, type ResourceBlueprint, use } from "@starbeam/resource"; +import { CONTEXT } from "@starbeam/runtime"; + +type Blueprint = ResourceBlueprint; + +export function Service( + blueprint: Blueprint, + description?: string | Description +): ResourceBlueprint { + return Resource(({ use }) => { + return CONTEXT.create(blueprint, () => { + return use(blueprint); + }); + }, Desc("blueprint:service", description).detail("service")); +} + +export function service( + resource: Blueprint, + description?: string | Description +): Resource { + return use(Service(resource, Desc("blueprint:resource", description)), { + lifetime: CONTEXT.app, + }); +} diff --git a/packages/universal/service/tests/.eslintrc.json b/packages/universal/service/tests/.eslintrc.json new file mode 100644 index 00000000..e72c7eb1 --- /dev/null +++ b/packages/universal/service/tests/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": false, + "overrides": [ + { + "extends": ["plugin:@starbeam/loose"], + "files": ["**/*.ts"], + "parserOptions": { + "project": "packages/universal/service/tests/tsconfig.json" + } + } + ] +} diff --git a/packages/universal/service/tests/.npmrc b/packages/universal/service/tests/.npmrc new file mode 100644 index 00000000..aed5b2b6 --- /dev/null +++ b/packages/universal/service/tests/.npmrc @@ -0,0 +1,2 @@ +auto-install-peers=true +strict-peer-dependencies=true diff --git a/packages/universal/service/tests/package.json b/packages/universal/service/tests/package.json new file mode 100644 index 00000000..3b71d262 --- /dev/null +++ b/packages/universal/service/tests/package.json @@ -0,0 +1,22 @@ +{ + "private": true, + "name": "@starbeam-tests/service", + "version": "1.0.0", + "type": "module", + "starbeam:type": "tests", + "scripts": { + "test:lint": "eslint", + "test:types": "tsc -b" + }, + "dependencies": { + "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/js": "workspace:^", + "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", + "@starbeam/runtime": "workspace:^", + "@starbeam/service": "workspace:^", + "@starbeam/shared": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^" + } +} diff --git a/packages/universal/service/tests/service.spec.ts b/packages/universal/service/tests/service.spec.ts new file mode 100644 index 00000000..54badaa8 --- /dev/null +++ b/packages/universal/service/tests/service.spec.ts @@ -0,0 +1,42 @@ +import { Cell, Marker } from "@starbeam/reactive"; +import { Resource } from "@starbeam/resource"; +import { CONTEXT } from "@starbeam/runtime"; +import { service } from "@starbeam/service"; +import { describe, expect, test } from "@starbeam-workspace/test-utils"; + +describe("service", () => { + test("should be able to create a service", () => { + const counts = { init: 0, finalized: 0 }; + const invalidate = Marker(); + const Counter = Resource(({ on }) => { + counts.init++; + invalidate.read(); + const count = Cell(0); + on.cleanup(() => counts.finalized++); + return { + get count() { + return count.current; + }, + increment() { + count.current++; + }, + }; + }); + + const app = {}; + CONTEXT.app = app; + const counter = service(Counter); + + expect(counter.current.count).toBe(0); + expect(counts.init).toBe(1); + + counter.current.increment(); + expect(counter.current.count).toBe(1); + expect(counts.init).toBe(1); + + invalidate.mark(); + expect(counter.current.count).toBe(0); + expect(counts.init).toBe(2); + expect(counts.finalized).toBe(1); + }); +}); diff --git a/packages/universal/service/tests/tsconfig.json b/packages/universal/service/tests/tsconfig.json new file mode 100644 index 00000000..28a12c31 --- /dev/null +++ b/packages/universal/service/tests/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../../dist/types", + "declarationMap": true, + "outDir": "../../../../dist/packages", + "types": ["../../../env"] + }, + "exclude": ["dist/**/*"], + "include": ["**/*.ts"] +} diff --git a/packages/universal/service/tsconfig.json b/packages/universal/service/tsconfig.json new file mode 100644 index 00000000..4790a1ab --- /dev/null +++ b/packages/universal/service/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../dist/types", + "declarationMap": true, + "outDir": "../../../dist/packages", + "types": ["../../env"] + }, + "exclude": ["dist/**/*"] +} diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index a5d3d0f8..32ea1581 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -17,13 +17,6 @@ export type { ReactiveFactory, } from "./src/reactive-core/reactive.js"; export { Reactive } from "./src/reactive-core/reactive.js"; -export { - createService, - reactiveService, - Service, - service, - type ServiceBlueprint, -} from "./src/reactive-core/service.js"; export { type Variant, type VariantEntry, @@ -45,5 +38,4 @@ export { type ResourceRun, use, } from "@starbeam/resource"; -export { ResourceList as ResourceList3 } from "@starbeam/resource/src/resource-list.js"; export { LIFETIME, PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts index 5faccc73..ed372d0b 100644 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ b/packages/universal/universal/src/reactive-core/reactive.ts @@ -64,4 +64,4 @@ function construct(constructor: ReactiveFactory): T | Reactive { } } -export type Blueprint = ResourceBlueprint; +export type Blueprint = ResourceBlueprint; diff --git a/packages/universal/universal/src/reactive-core/service.ts b/packages/universal/universal/src/reactive-core/service.ts deleted file mode 100644 index 74f5bdce..00000000 --- a/packages/universal/universal/src/reactive-core/service.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Desc } from "@starbeam/debug"; -import type { Description, Reactive } from "@starbeam/interfaces"; -import { Resource, type ResourceBlueprint } from "@starbeam/resource"; -import { CONTEXT } from "@starbeam/runtime"; - -import { Factory, type IntoResource } from "./into.js"; -import { type Blueprint } from "./reactive.js"; - -export function Service( - blueprint: Blueprint, - description?: string | Description -): ResourceBlueprint | ResourceBlueprint> { - return Resource(({ use }) => { - return CONTEXT.create(blueprint, () => { - return use(blueprint); - }); - }, Desc("blueprint:service", description).detail("service")); -} - -Service.create = ( - create: Blueprint, - description?: string | Description -): Reactive => { - return createService(create, Desc("service", description)); -}; - -export class ServiceBlueprint { - #create: IntoResource; - #description: Description; - - constructor(create: IntoResource, description: Description) { - this.#create = create; - this.#description = description; - } - - create(): Reactive { - return createService(this.#create, this.#description); - } -} - -export function createService( - resource: IntoResource, - description: Description, - app = CONTEXT.app -): Reactive { - CONTEXT.app = app; - return CONTEXT.create(resource, () => - Factory.resource(resource, app, description) - ); -} - -export function reactiveService( - factory: Blueprint | ResourceBlueprint, - description?: string | Description -): Reactive { - return createService(factory, Desc("service", description)); -} - -export function service( - factory: Blueprint, - description?: string | Description -): T { - return createService(factory, Desc("service", description)).current; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4bce8e0..981e0dec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -136,13 +136,13 @@ importers: dependencies: '@rollup/plugin-commonjs': specifier: ^24.0.0 - version: 24.0.0 + version: 24.0.0(rollup@3.9.1) '@types/@rollup/plugin-node-resolve': dependencies: '@rollup/plugin-node-resolve': specifier: ^15.0.1 - version: 15.0.1 + version: 15.0.1(rollup@3.9.1) '@types/ansicolor': devDependencies: @@ -194,13 +194,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) demos/preact-hello-world: dependencies: @@ -231,13 +231,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react: dependencies: @@ -271,13 +271,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-jsnation: dependencies: @@ -314,7 +314,7 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) @@ -388,13 +388,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-query: dependencies: @@ -443,13 +443,13 @@ importers: version: 5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-stock-ticker: dependencies: @@ -489,13 +489,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-store: dependencies: @@ -535,13 +535,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) packages/preact/preact: dependencies: @@ -824,7 +824,7 @@ importers: version: 18.2.0 vitest: specifier: '*' - version: 0.29.7(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) packages/react/test-utils: dependencies: @@ -1178,6 +1178,64 @@ importers: specifier: workspace:^ version: link:../../shared + packages/universal/service: + dependencies: + '@starbeam/core-utils': + specifier: workspace:^ + version: link:../core-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../resource + '@starbeam/runtime': + specifier: workspace:^ + version: link:../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + devDependencies: + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + + packages/universal/service/tests: + dependencies: + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../test-utils + '@starbeam/debug': + specifier: workspace:^ + version: link:../../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../interfaces + '@starbeam/js': + specifier: workspace:^ + version: link:../../js + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../../resource + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../runtime + '@starbeam/service': + specifier: workspace:^ + version: link:.. + '@starbeam/shared': + specifier: workspace:^ + version: link:../../shared + packages/universal/shared: devDependencies: '@starbeam-dev/build-support': @@ -1341,7 +1399,7 @@ importers: version: 10.11.3 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-mpa: specifier: ^1.1.3 version: 1.1.4 @@ -1491,7 +1549,7 @@ importers: version: 8.8.0(eslint@8.36.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint@8.36.0) + version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) eslint-plugin-json: specifier: ^3.1.0 version: 3.1.0 @@ -1503,7 +1561,7 @@ importers: version: 10.0.0(eslint@8.36.0) eslint-plugin-unused-imports: specifier: ^2.0.0 - version: 2.0.0(eslint@8.36.0) + version: 2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0) magic-string: specifier: ^0.27.0 version: 0.27.0 @@ -1521,7 +1579,7 @@ importers: version: 4.0.2(postcss@8.4.20) rollup-plugin-ts: specifier: '*' - version: 3.0.2(rollup@3.9.1)(typescript@5.0.2) + version: 3.0.2(@babel/core@7.21.3)(@babel/plugin-transform-runtime@7.21.0)(@babel/preset-env@7.20.2)(@babel/preset-typescript@7.21.0)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.2) vite: specifier: 4.2.1 version: 4.2.1(@types/node@18.15.5) @@ -1849,7 +1907,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.1.1 '@jridgewell/trace-mapping': 0.3.17 - dev: true /@babel/code-frame@7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} @@ -1860,12 +1917,10 @@ packages: /@babel/compat-data@7.20.1: resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/compat-data@7.21.0: resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} engines: {node: '>=6.9.0'} - dev: true /@babel/core@7.21.3: resolution: {integrity: sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==} @@ -1882,13 +1937,12 @@ packages: '@babel/traverse': 7.21.3 '@babel/types': 7.21.3 convert-source-map: 1.9.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/eslint-parser@7.21.3(@babel/core@7.21.3)(eslint@8.36.0): resolution: {integrity: sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==} @@ -1919,7 +1973,6 @@ packages: '@babel/types': 7.21.3 '@jridgewell/gen-mapping': 0.3.2 jsesc: 2.5.2 - dev: true /@babel/generator@7.21.3: resolution: {integrity: sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==} @@ -1929,14 +1982,12 @@ packages: '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.17 jsesc: 2.5.2 - dev: true /@babel/helper-annotate-as-pure@7.18.6: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 - dev: true /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} @@ -1944,7 +1995,6 @@ packages: dependencies: '@babel/helper-explode-assignable-expression': 7.18.6 '@babel/types': 7.20.7 - dev: true /@babel/helper-compilation-targets@7.20.0(@babel/core@7.21.3): resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} @@ -1957,7 +2007,6 @@ packages: '@babel/helper-validator-option': 7.18.6 browserslist: 4.21.4 semver: 6.3.0 - dev: true /@babel/helper-compilation-targets@7.20.7(@babel/core@7.21.3): resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} @@ -1971,7 +2020,6 @@ packages: browserslist: 4.21.4 lru-cache: 5.1.1 semver: 6.3.0 - dev: true /@babel/helper-create-class-features-plugin@7.20.7(@babel/core@7.21.3): resolution: {integrity: sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w==} @@ -1989,7 +2037,6 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} @@ -2008,7 +2055,6 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-create-regexp-features-plugin@7.19.0(@babel/core@7.21.3): resolution: {integrity: sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==} @@ -2019,7 +2065,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 regexpu-core: 5.2.1 - dev: true /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.3): resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} @@ -2029,13 +2074,12 @@ packages: '@babel/core': 7.21.3 '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.1 semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-environment-visitor@7.18.9: resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} @@ -2046,7 +2090,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 - dev: true /@babel/helper-function-name@7.19.0: resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} @@ -2061,7 +2104,6 @@ packages: dependencies: '@babel/template': 7.20.7 '@babel/types': 7.21.3 - dev: true /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} @@ -2074,21 +2116,18 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 - dev: true /@babel/helper-member-expression-to-functions@7.21.0: resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.3 - dev: true /@babel/helper-module-imports@7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - dev: true /@babel/helper-module-transforms@7.20.2: resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} @@ -2104,7 +2143,6 @@ packages: '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-module-transforms@7.21.2: resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} @@ -2120,19 +2158,16 @@ packages: '@babel/types': 7.21.3 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-optimise-call-expression@7.18.6: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - dev: true /@babel/helper-plugin-utils@7.20.2: resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} @@ -2147,7 +2182,6 @@ packages: '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-replace-supers@7.20.7: resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} @@ -2161,21 +2195,18 @@ packages: '@babel/types': 7.20.7 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-simple-access@7.20.2: resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - dev: true /@babel/helper-skip-transparent-expression-wrappers@7.20.0: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.7 - dev: true /@babel/helper-split-export-declaration@7.18.6: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} @@ -2194,12 +2225,10 @@ packages: /@babel/helper-validator-option@7.18.6: resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-option@7.21.0: resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-wrap-function@7.19.0: resolution: {integrity: sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==} @@ -2211,7 +2240,6 @@ packages: '@babel/types': 7.21.3 transitivePeerDependencies: - supports-color - dev: true /@babel/helpers@7.21.0: resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} @@ -2222,7 +2250,6 @@ packages: '@babel/types': 7.21.3 transitivePeerDependencies: - supports-color - dev: true /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} @@ -2260,7 +2287,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.21.3 - dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} @@ -2270,7 +2296,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==} @@ -2282,7 +2307,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-async-generator-functions@7.20.1(@babel/core@7.21.3): resolution: {integrity: sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==} @@ -2297,7 +2321,6 @@ packages: '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} @@ -2310,7 +2333,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-class-static-block@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==} @@ -2324,7 +2346,6 @@ packages: '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} @@ -2351,7 +2372,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} @@ -2362,7 +2382,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} @@ -2373,7 +2392,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-logical-assignment-operators@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==} @@ -2384,7 +2402,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} @@ -2395,7 +2412,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} @@ -2406,7 +2422,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-object-rest-spread@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==} @@ -2420,7 +2435,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} @@ -2431,7 +2445,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-optional-chaining@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==} @@ -2443,7 +2456,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) - dev: true /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} @@ -2456,7 +2468,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-private-property-in-object@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==} @@ -2471,7 +2482,6 @@ packages: '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} @@ -2482,7 +2492,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.3): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} @@ -2491,7 +2500,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.3): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} @@ -2500,7 +2508,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.3): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} @@ -2510,7 +2517,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} @@ -2529,7 +2535,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} @@ -2538,7 +2543,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.21.3): resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} @@ -2548,7 +2552,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} @@ -2557,7 +2560,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} @@ -2576,7 +2578,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} @@ -2585,7 +2586,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.3): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} @@ -2594,7 +2594,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} @@ -2603,7 +2602,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} @@ -2612,7 +2610,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.3): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} @@ -2621,7 +2618,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.3): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} @@ -2631,7 +2627,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.3): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} @@ -2641,7 +2636,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.21.3): resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} @@ -2651,7 +2645,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-arrow-functions@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==} @@ -2661,7 +2654,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-async-to-generator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==} @@ -2675,7 +2667,6 @@ packages: '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} @@ -2685,7 +2676,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-block-scoping@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==} @@ -2695,7 +2685,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-classes@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==} @@ -2715,7 +2704,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-computed-properties@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==} @@ -2725,7 +2713,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-destructuring@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==} @@ -2735,7 +2722,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} @@ -2746,7 +2732,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} @@ -2756,7 +2741,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} @@ -2767,7 +2751,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-for-of@7.18.8(@babel/core@7.21.3): resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} @@ -2777,7 +2760,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} @@ -2789,7 +2771,6 @@ packages: '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) '@babel/helper-function-name': 7.19.0 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-literals@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} @@ -2799,7 +2780,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} @@ -2809,7 +2789,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-modules-amd@7.19.6(@babel/core@7.21.3): resolution: {integrity: sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==} @@ -2822,7 +2801,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-modules-commonjs@7.19.6(@babel/core@7.21.3): resolution: {integrity: sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==} @@ -2836,7 +2814,6 @@ packages: '@babel/helper-simple-access': 7.20.2 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-modules-systemjs@7.19.6(@babel/core@7.21.3): resolution: {integrity: sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==} @@ -2851,7 +2828,6 @@ packages: '@babel/helper-validator-identifier': 7.19.1 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} @@ -2864,7 +2840,6 @@ packages: '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-named-capturing-groups-regex@7.19.1(@babel/core@7.21.3): resolution: {integrity: sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==} @@ -2875,7 +2850,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} @@ -2885,7 +2859,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} @@ -2898,7 +2871,6 @@ packages: '@babel/helper-replace-supers': 7.20.7 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-parameters@7.20.3(@babel/core@7.21.3): resolution: {integrity: sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==} @@ -2908,7 +2880,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} @@ -2918,7 +2889,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} @@ -2974,7 +2944,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 regenerator-transform: 0.15.0 - dev: true /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} @@ -2984,7 +2953,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-runtime@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==} @@ -3001,7 +2969,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} @@ -3011,7 +2978,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-spread@7.19.0(@babel/core@7.21.3): resolution: {integrity: sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==} @@ -3022,7 +2988,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - dev: true /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} @@ -3032,7 +2997,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} @@ -3042,7 +3006,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.21.3): resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} @@ -3052,7 +3015,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.21.3): resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} @@ -3067,7 +3029,6 @@ packages: '@babel/plugin-syntax-typescript': 7.20.0(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.21.3): resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} @@ -3077,7 +3038,6 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} @@ -3088,7 +3048,6 @@ packages: '@babel/core': 7.21.3 '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/preset-env@7.20.2(@babel/core@7.21.3): resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} @@ -3174,7 +3133,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/preset-modules@0.1.5(@babel/core@7.21.3): resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} @@ -3187,7 +3145,6 @@ packages: '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) '@babel/types': 7.20.2 esutils: 2.0.3 - dev: true /@babel/preset-react@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} @@ -3216,7 +3173,6 @@ packages: '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /@babel/runtime@7.21.0: resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} @@ -3232,24 +3188,6 @@ packages: '@babel/parser': 7.20.7 '@babel/types': 7.21.3 - /@babel/traverse@7.20.1: - resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.4 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.3 - '@babel/types': 7.20.2 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/traverse@7.20.1(supports-color@5.5.0): resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} engines: {node: '>=6.9.0'} @@ -3266,7 +3204,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/traverse@7.20.10: resolution: {integrity: sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg==} @@ -3280,11 +3217,10 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 '@babel/parser': 7.20.7 '@babel/types': 7.21.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/traverse@7.21.3: resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} @@ -3298,11 +3234,10 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 '@babel/parser': 7.21.3 '@babel/types': 7.21.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/types@7.20.2: resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==} @@ -3526,7 +3461,7 @@ packages: acorn-walk: 8.2.0 cheerio: 1.0.0-rc.12 connect-injector: 0.4.4 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) es-module-lexer: 0.10.5 fast-glob: 3.2.12 fs-extra: 10.1.0 @@ -3798,7 +3733,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) espree: 9.4.1 globals: 13.19.0 ignore: 5.2.0 @@ -3815,7 +3750,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) espree: 9.5.0 globals: 13.19.0 ignore: 5.2.0 @@ -3840,7 +3775,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -3858,7 +3793,6 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.14 - dev: true /@jridgewell/gen-mapping@0.3.2: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} @@ -3946,24 +3880,6 @@ packages: /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} - dev: true - - /@rollup/plugin-commonjs@24.0.0: - resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2 - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.0.3 - is-reference: 1.2.1 - magic-string: 0.27.0 - dev: false /@rollup/plugin-commonjs@24.0.0(rollup@3.9.1): resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} @@ -3998,23 +3914,6 @@ packages: rollup: 3.9.1 dev: false - /@rollup/plugin-node-resolve@15.0.1: - resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2 - '@types/resolve': 1.20.2 - deepmerge: 4.2.2 - is-builtin-module: 3.2.0 - is-module: 1.0.0 - resolve: 1.22.1 - dev: false - /@rollup/plugin-node-resolve@15.0.1(rollup@3.9.1): resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} @@ -4040,20 +3939,6 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 - /@rollup/pluginutils@5.0.2: - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.0 - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: false - /@rollup/pluginutils@5.0.2(rollup@3.9.1): resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} @@ -4362,7 +4247,7 @@ packages: '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/type-utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) '@typescript-eslint/utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) eslint: 8.36.0 grapheme-splitter: 1.0.4 ignore: 5.2.0 @@ -4386,7 +4271,7 @@ packages: '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/types': 5.56.0 '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) eslint: 8.36.0 typescript: 5.0.2 transitivePeerDependencies: @@ -4411,7 +4296,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) '@typescript-eslint/utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) eslint: 8.36.0 tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 @@ -4433,7 +4318,7 @@ packages: dependencies: '@typescript-eslint/types': 5.56.0 '@typescript-eslint/visitor-keys': 5.56.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.8 @@ -4527,7 +4412,6 @@ packages: pathe: 1.1.0 picocolors: 1.0.0 sirv: 2.0.2 - dev: true /@vitest/utils@0.29.7: resolution: {integrity: sha512-vNgGadp2eE5XKCXtZXL5UyNEDn68npSct75OC9AlELenSK0DiV1Mb9tfkwJHKjRb69iek+e79iipoJx8+s3SdA==} @@ -4641,7 +4525,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -4822,7 +4706,6 @@ packages: semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.21.3): resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} @@ -4834,7 +4717,6 @@ packages: core-js-compat: 3.26.0 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.21.3): resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} @@ -4845,7 +4727,6 @@ packages: '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) transitivePeerDependencies: - supports-color - dev: true /babel-plugin-styled-components@2.0.7(styled-components@5.3.6): resolution: {integrity: sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==} @@ -5229,13 +5110,11 @@ packages: /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true /core-js-compat@3.26.0: resolution: {integrity: sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==} dependencies: browserslist: 4.21.4 - dev: true /cosmiconfig@7.0.1: resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} @@ -5327,7 +5206,6 @@ packages: /css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - dev: true /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -5490,17 +5368,6 @@ packages: dependencies: ms: 2.1.3 - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - /debug@4.3.4(supports-color@5.5.0): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -5512,7 +5379,6 @@ packages: dependencies: ms: 2.1.2 supports-color: 5.5.0 - dev: true /decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} @@ -5595,11 +5461,11 @@ packages: hasBin: true dependencies: '@babel/parser': 7.16.4 - '@babel/traverse': 7.20.1 + '@babel/traverse': 7.20.1(supports-color@5.5.0) '@vue/compiler-sfc': 3.2.41 camelcase: 6.3.0 cosmiconfig: 7.0.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) deps-regex: 0.1.4 ignore: 5.2.0 is-core-module: 2.11.0 @@ -6145,7 +6011,7 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) enhanced-resolve: 5.10.0 eslint: 8.36.0 eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) @@ -6186,35 +6052,6 @@ packages: transitivePeerDependencies: - supports-color - /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint@8.36.0): - resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - debug: 3.2.7 - eslint: 8.36.0 - eslint-import-resolver-node: 0.3.7 - transitivePeerDependencies: - - supports-color - dev: false - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} @@ -6247,39 +6084,6 @@ packages: - eslint-import-resolver-webpack - supports-color - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint@8.36.0): - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - array-includes: 3.1.6 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.1 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.36.0 - eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint@8.36.0) - has: 1.0.3 - is-core-module: 2.11.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.6 - resolve: 1.22.1 - semver: 6.3.0 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: false - /eslint-plugin-json@3.1.0: resolution: {integrity: sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==} engines: {node: '>=12.0'} @@ -6394,20 +6198,6 @@ packages: eslint: 8.36.0 eslint-rule-composer: 0.3.0 - /eslint-plugin-unused-imports@2.0.0(eslint@8.36.0): - resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - dependencies: - eslint: 8.36.0 - eslint-rule-composer: 0.3.0 - dev: false - /eslint-rule-composer@0.3.0: resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} engines: {node: '>=4.0.0'} @@ -6450,7 +6240,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 @@ -6714,7 +6504,6 @@ packages: /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - dev: true /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} @@ -6840,7 +6629,6 @@ packages: whatwg-mimetype: 3.0.0 transitivePeerDependencies: - encoding - dev: true /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} @@ -6882,7 +6670,6 @@ packages: /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - dev: true /helpertypes@0.0.18: resolution: {integrity: sha512-XRhfbSEmR+poXUC5/8AbmYNJb2riOT6qPzjGJZr0S9YedHiaY+/tzPYzWMUclYMEdCYo/1l8PDYrQFCj02v97w==} @@ -6924,7 +6711,7 @@ packages: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -6933,7 +6720,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -7349,7 +7136,6 @@ packages: /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true - dev: true /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} @@ -7387,7 +7173,6 @@ packages: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - dev: true /jsonc-eslint-parser@2.1.0: resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==} @@ -7511,7 +7296,6 @@ packages: /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -7553,7 +7337,6 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 - dev: true /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} @@ -7687,7 +7470,6 @@ packages: /mrmime@1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} engines: {node: '>=10'} - dev: true /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -7735,7 +7517,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-pty@0.10.1: resolution: {integrity: sha512-JTdtUS0Im/yRsWJSx7yiW9rtpfmxqxolrtnyKwPLI+6XqTAPW/O2MjS8FYL4I5TsMbH2lVgDb2VMjp+9LoQGNg==} @@ -8670,11 +8451,9 @@ packages: engines: {node: '>=4'} dependencies: regenerate: 1.4.2 - dev: true /regenerate@1.4.2: resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true /regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} @@ -8683,7 +8462,6 @@ packages: resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} dependencies: '@babel/runtime': 7.21.0 - dev: true /regexp.prototype.flags@1.4.3: resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} @@ -8703,18 +8481,15 @@ packages: regjsparser: 0.9.1 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.0.0 - dev: true /regjsgen@0.7.1: resolution: {integrity: sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==} - dev: true /regjsparser@0.9.1: resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} hasBin: true dependencies: jsesc: 0.5.0 - dev: true /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -8799,7 +8574,7 @@ packages: - ts-node dev: false - /rollup-plugin-ts@3.0.2(rollup@3.9.1)(typescript@5.0.2): + /rollup-plugin-ts@3.0.2(@babel/core@7.21.3)(@babel/plugin-transform-runtime@7.21.0)(@babel/preset-env@7.20.2)(@babel/preset-typescript@7.21.0)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.2): resolution: {integrity: sha512-67qi2QTHewhLyKDG6fX3jpohWpmUPPIT/xJ7rsYK46X6MqmoWy64Ti0y8ygPfLv8mXDCdRZUofM3mTxDfCswRA==} engines: {node: '>=14.9.0', npm: '>=7.0.0', pnpm: '>=3.2.0', yarn: '>=1.13'} peerDependencies: @@ -8828,6 +8603,11 @@ packages: '@swc/helpers': optional: true dependencies: + '@babel/core': 7.21.3 + '@babel/plugin-transform-runtime': 7.21.0(@babel/core@7.21.3) + '@babel/preset-env': 7.20.2(@babel/core@7.21.3) + '@babel/preset-typescript': 7.21.0(@babel/core@7.21.3) + '@babel/runtime': 7.21.0 '@rollup/pluginutils': 4.2.1 '@wessberg/stringutil': 1.0.19 ansi-colors: 4.1.3 @@ -9005,7 +8785,6 @@ packages: '@polka/url': 1.0.0-next.21 mrmime: 1.0.1 totalist: 3.0.0 - dev: true /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -9337,7 +9116,6 @@ packages: /totalist@3.0.0: resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} engines: {node: '>=6'} - dev: true /tough-cookie@4.1.2: resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} @@ -9350,7 +9128,6 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} @@ -9489,7 +9266,6 @@ packages: /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} - dev: true /unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} @@ -9497,17 +9273,14 @@ packages: dependencies: unicode-canonical-property-names-ecmascript: 2.0.0 unicode-property-aliases-ecmascript: 2.1.0 - dev: true /unicode-match-property-value-ecmascript@2.0.0: resolution: {integrity: sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==} engines: {node: '>=4'} - dev: true /unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} - dev: true /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} @@ -9561,7 +9334,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 @@ -9581,7 +9354,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 @@ -9602,7 +9375,7 @@ packages: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 dependencies: fast-glob: 3.2.12 - vite: 4.2.1 + vite: 4.2.1(@types/node@18.15.5) /vite-plugin-mpa@1.1.4: resolution: {integrity: sha512-sLXMOdMl8t9B9/sxXXZ9CLt8QudhGSSKCX+bZ/ePaO7kp4SdoA5d6CV+EnCyNuQCenAbXKJzk3nM8Do0RgmSpA==} @@ -9612,38 +9385,6 @@ packages: yargs: 16.2.0 dev: true - /vite@4.2.1: - resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.17.12 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.9.1 - optionalDependencies: - fsevents: 2.3.2 - /vite@4.2.1(@types/node@18.15.5): resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -9677,7 +9418,7 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vitest@0.29.7(@vitest/ui@0.29.7): + /vitest@0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1): resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9717,7 +9458,9 @@ packages: acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) + happy-dom: 8.9.0 + jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 picocolors: 1.0.0 @@ -9739,7 +9482,7 @@ packages: - terser dev: true - /vitest@0.29.7(jsdom@21.1.1): + /vitest@0.29.7(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1): resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9773,12 +9516,14 @@ packages: '@vitest/expect': 0.29.7 '@vitest/runner': 0.29.7 '@vitest/spy': 0.29.7 + '@vitest/ui': 0.29.8 '@vitest/utils': 0.29.7 acorn: 8.8.2 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) + happy-dom: 8.9.0 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 @@ -9844,7 +9589,7 @@ packages: acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) happy-dom: 8.9.0 jsdom: 21.1.1 local-pkg: 0.4.2 @@ -9908,7 +9653,6 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -9943,7 +9687,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -10084,7 +9827,6 @@ packages: /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} From f7efabbb652d05dfafac7360b8105014261cec0a Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Wed, 29 Mar 2023 18:02:08 -0400 Subject: [PATCH 22/46] Update to pnpm 8 --- .../actions/setup-node-and-install/action.yml | 20 - .github/workflows/ci.yml | 36 +- pnpm-lock.yaml | 2790 +++++++---------- 3 files changed, 1162 insertions(+), 1684 deletions(-) delete mode 100644 .github/actions/setup-node-and-install/action.yml diff --git a/.github/actions/setup-node-and-install/action.yml b/.github/actions/setup-node-and-install/action.yml deleted file mode 100644 index 463abd20..00000000 --- a/.github/actions/setup-node-and-install/action.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Setup node and install dependencies -description: Setup node and install dependencies using pnpm -runs: - using: "composite" - steps: - - uses: actions/setup-node@v2 - with: - node-version: '16' - - name: Cache pnpm modules - uses: actions/cache@v2 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - uses: pnpm/action-setup@v2.0.1 - with: - version: 7.6.0 - - run: pnpm install --frozen-lockfile - shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d04195f..89e28db9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,28 +15,9 @@ jobs: steps: - uses: actions/checkout@v2 + - uses: NullVoxPopuli/action-setup-pnpm@v2 - name: "Setup node and install dependencies" uses: ./.github/actions/setup-node-and-install - # currently not used - as tests, lints, etc are all top-level commands / projects - # if we were to make each workspace isolated, we'd first need to copy tsc/eslint/vitest - # configs into each package -- but that would be slower than what today's setup is. - - id: set-matrix - name: "Find workspaces" - # generates a list of root-relative paths to each workspace - # - # the pipes line-by-line: - # Remove version information - # Remove the current directory - # Remove empty lines - # Remove leading slashes - run: | - root_of_repo=$(git rev-parse --show-toplevel) - workspaces=$(pnpm ls -r --depth -1 --long --parseable \ - | cut -f1 -d':' \ - | sed "s~$root_of_repo~~g" \ - | sed '/^[[:space:]]*$/d' \ - | sed 's~^/~~g') - echo "::set-output name=matrix::$(echo $workspaces)" test: name: "Tests" @@ -44,8 +25,7 @@ jobs: needs: ["install_dependencies"] steps: - uses: actions/checkout@v2 - - name: "Setup node and install dependencies" - uses: ./.github/actions/setup-node-and-install + - uses: NullVoxPopuli/action-setup-pnpm@v2 - run: pnpm ci:specs test_prod: @@ -54,8 +34,7 @@ jobs: needs: ["install_dependencies"] steps: - uses: actions/checkout@v2 - - name: "Setup node and install dependencies" - uses: ./.github/actions/setup-node-and-install + - uses: NullVoxPopuli/action-setup-pnpm@v2 - run: pnpm ci:prod typecheck: @@ -64,8 +43,7 @@ jobs: needs: ["install_dependencies"] steps: - uses: actions/checkout@v2 - - name: "Setup node and install dependencies" - uses: ./.github/actions/setup-node-and-install + - uses: NullVoxPopuli/action-setup-pnpm@v2 - run: pnpm ci:types lint: @@ -74,8 +52,7 @@ jobs: needs: ["install_dependencies"] steps: - uses: actions/checkout@v2 - - name: "Setup node and install dependencies" - uses: ./.github/actions/setup-node-and-install + - uses: NullVoxPopuli/action-setup-pnpm@v2 - run: pnpm ci:lint release: @@ -85,5 +62,4 @@ jobs: steps: - uses: actions/checkout@v2 - - name: "Setup node and install dependencies" - uses: ./.github/actions/setup-node-and-install + - uses: NullVoxPopuli/action-setup-pnpm@v2 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4bce8e0..cb2c72f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,25 +25,25 @@ importers: devDependencies: '@babel/eslint-parser': specifier: ^7.21.3 - version: 7.21.3(@babel/core@7.21.3)(eslint@8.36.0) + version: 7.21.3(@babel/core@7.19.1)(eslint@8.36.0) '@babel/plugin-proposal-decorators': specifier: ^7.21.0 - version: 7.21.0(@babel/core@7.21.3) + version: 7.21.0(@babel/core@7.19.1) '@babel/plugin-syntax-dynamic-import': specifier: ^7.8.3 - version: 7.8.3(@babel/core@7.21.3) + version: 7.8.3(@babel/core@7.19.1) '@babel/plugin-transform-runtime': specifier: ^7.21.0 - version: 7.21.0(@babel/core@7.21.3) + version: 7.21.0(@babel/core@7.19.1) '@babel/preset-env': specifier: ^7.20.2 - version: 7.20.2(@babel/core@7.21.3) + version: 7.20.2(@babel/core@7.19.1) '@babel/preset-react': specifier: ^7.18.6 - version: 7.18.6(@babel/core@7.21.3) + version: 7.18.6(@babel/core@7.19.1) '@babel/preset-typescript': specifier: ^7.21.0 - version: 7.21.0(@babel/core@7.21.3) + version: 7.21.0(@babel/core@7.19.1) '@babel/runtime': specifier: ^7.21.0 version: 7.21.0 @@ -82,7 +82,7 @@ importers: version: 8.36.0 eslint-config-airbnb: specifier: ^19.0.4 - version: 19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.36.0) + version: 19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.6.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.31.8)(eslint@8.36.0) eslint-config-prettier: specifier: ^8.8.0 version: 8.8.0(eslint@8.36.0) @@ -136,13 +136,13 @@ importers: dependencies: '@rollup/plugin-commonjs': specifier: ^24.0.0 - version: 24.0.0 + version: 24.0.0(rollup@3.9.1) '@types/@rollup/plugin-node-resolve': dependencies: '@rollup/plugin-node-resolve': specifier: ^15.0.1 - version: 15.0.1 + version: 15.0.1(rollup@3.9.1) '@types/ansicolor': devDependencies: @@ -188,19 +188,19 @@ importers: devDependencies: '@esbuild-plugins/node-globals-polyfill': specifier: ^0.1.1 - version: 0.1.1(esbuild@0.17.12) + version: 0.1.1(esbuild@0.17.15) '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.23.4 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.23.4)(happy-dom@8.9.0)(jsdom@21.1.1) demos/preact-hello-world: dependencies: @@ -225,19 +225,19 @@ importers: devDependencies: '@esbuild-plugins/node-globals-polyfill': specifier: ^0.1.1 - version: 0.1.1(esbuild@0.17.12) + version: 0.1.1(esbuild@0.17.15) '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react: dependencies: @@ -262,22 +262,22 @@ importers: devDependencies: '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 '@types/react-dom': specifier: ^18.0.10 version: 18.0.10 '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-jsnation: dependencies: @@ -305,16 +305,16 @@ importers: devDependencies: '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 '@types/react-dom': specifier: ^18.0.10 version: 18.0.10 '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) @@ -345,7 +345,7 @@ importers: version: 13.4.0(react-dom@18.2.0)(react@18.2.0) '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 demos/react-lite-query: dependencies: @@ -379,22 +379,22 @@ importers: devDependencies: '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 '@types/react-dom': specifier: ^18.0.10 version: 18.0.10 '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-query: dependencies: @@ -425,31 +425,31 @@ importers: version: 10.16.1(react-dom@18.2.0)(react@18.2.0) '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 '@types/react-dom': specifier: ^18.0.10 version: 18.0.10 '@types/styled-components': specifier: ^5.1.25 - version: 5.1.26 + version: 5.1.25 '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 axios: specifier: ^1.2.2 version: 1.2.2 styled-components: specifier: ^5.3.5 - version: 5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) + version: 5.3.5(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0) vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-stock-ticker: dependencies: @@ -477,7 +477,7 @@ importers: devDependencies: '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 '@types/react-dom': specifier: ^18.0.10 version: 18.0.10 @@ -486,16 +486,16 @@ importers: version: 4.0.4 '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) demos/react-store: dependencies: @@ -526,22 +526,22 @@ importers: devDependencies: '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 '@types/react-dom': specifier: ^18.0.10 version: 18.0.10 '@vitest/ui': specifier: '*' - version: 0.29.7 + version: 0.29.8 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) packages/preact/preact: dependencies: @@ -824,7 +824,7 @@ importers: version: 18.2.0 vitest: specifier: '*' - version: 0.29.7(jsdom@21.1.1) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) packages/react/test-utils: dependencies: @@ -858,7 +858,7 @@ importers: version: 14.0.0(react-dom@18.2.0)(react@18.2.0) '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 packages/react/use-strict-lifecycle: dependencies: @@ -874,7 +874,7 @@ importers: version: link:../../../workspace/build '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 packages/react/use-strict-lifecycle/tests: dependencies: @@ -893,7 +893,7 @@ importers: devDependencies: '@types/react': specifier: ^18.0.26 - version: 18.0.26 + version: 18.0.28 jsdom: specifier: ^20.0.3 version: 20.0.3 @@ -1335,16 +1335,16 @@ importers: version: 0.1.159 dirfilename: specifier: ^1.0.4 - version: 1.1.1 + version: 1.0.4 preact: specifier: ^10.11.3 version: 10.11.3 vite: specifier: 4.2.1 - version: 4.2.1 + version: 4.2.1(@types/node@18.15.5) vite-plugin-mpa: specifier: ^1.1.3 - version: 1.1.4 + version: 1.1.3 packages/x/store: dependencies: @@ -1363,7 +1363,7 @@ importers: dependencies: '@faker-js/faker': specifier: ^7.5.0 - version: 7.6.0 + version: 7.5.0 '@starbeam/universal': specifier: workspace:^ version: link:../../../universal/universal @@ -1461,7 +1461,7 @@ importers: dependencies: '@esbuild-plugins/node-globals-polyfill': specifier: ^0.1.1 - version: 0.1.1(esbuild@0.17.12) + version: 0.1.1(esbuild@0.17.15) '@eslint/eslintrc': specifier: ^1.4.1 version: 1.4.1 @@ -1491,7 +1491,7 @@ importers: version: 8.8.0(eslint@8.36.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint@8.36.0) + version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) eslint-plugin-json: specifier: ^3.1.0 version: 3.1.0 @@ -1503,7 +1503,7 @@ importers: version: 10.0.0(eslint@8.36.0) eslint-plugin-unused-imports: specifier: ^2.0.0 - version: 2.0.0(eslint@8.36.0) + version: 2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0) magic-string: specifier: ^0.27.0 version: 0.27.0 @@ -1521,7 +1521,7 @@ importers: version: 4.0.2(postcss@8.4.20) rollup-plugin-ts: specifier: '*' - version: 3.0.2(rollup@3.9.1)(typescript@5.0.2) + version: 3.0.2(@babel/core@7.19.1)(@babel/plugin-transform-runtime@7.21.0)(@babel/preset-env@7.20.2)(@babel/preset-typescript@7.21.0)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.2) vite: specifier: 4.2.1 version: 4.2.1(@types/node@18.15.5) @@ -1728,13 +1728,13 @@ importers: version: 5.2.0 commander: specifier: ^9.3.0 - version: 9.4.1 + version: 9.4.0 depcheck: specifier: ^1.4.3 version: 1.4.3 dirfilename: specifier: ^1.0.4 - version: 1.1.1 + version: 1.0.4 emoji-regex: specifier: ^10.2.1 version: 10.2.1 @@ -1749,7 +1749,7 @@ importers: version: 0.10.1 prettier: specifier: ^2.8.1 - version: 2.8.1 + version: 2.8.6 shell-escape-tag: specifier: ^2.0.2 version: 2.0.2 @@ -1849,7 +1849,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.1.1 '@jridgewell/trace-mapping': 0.3.17 - dev: true /@babel/code-frame@7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} @@ -1857,147 +1856,103 @@ packages: dependencies: '@babel/highlight': 7.18.6 - /@babel/compat-data@7.20.1: - resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==} + /@babel/code-frame@7.21.4: + resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} engines: {node: '>=6.9.0'} - dev: true + dependencies: + '@babel/highlight': 7.18.6 - /@babel/compat-data@7.21.0: - resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} + /@babel/compat-data@7.21.4: + resolution: {integrity: sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==} engines: {node: '>=6.9.0'} - dev: true - /@babel/core@7.21.3: - resolution: {integrity: sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==} + /@babel/core@7.19.1: + resolution: {integrity: sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.21.3 - '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.1) '@babel/helper-module-transforms': 7.21.2 - '@babel/helpers': 7.21.0 - '@babel/parser': 7.21.3 + '@babel/helpers': 7.19.0 + '@babel/parser': 7.21.4 '@babel/template': 7.20.7 - '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 - convert-source-map: 1.9.0 - debug: 4.3.4 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + convert-source-map: 1.8.0 + debug: 4.3.4(supports-color@5.5.0) gensync: 1.0.0-beta.2 - json5: 2.2.3 + json5: 2.2.1 semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/eslint-parser@7.21.3(@babel/core@7.21.3)(eslint@8.36.0): + /@babel/eslint-parser@7.21.3(@babel/core@7.19.1)(eslint@8.36.0): resolution: {integrity: sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: '@babel/core': '>=7.11.0' eslint: ^7.5.0 || ^8.0.0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 eslint: 8.36.0 eslint-visitor-keys: 2.1.0 semver: 6.3.0 dev: true - /@babel/generator@7.20.4: - resolution: {integrity: sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.21.3 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - - /@babel/generator@7.20.7: - resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} + /@babel/generator@7.19.0: + resolution: {integrity: sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 '@jridgewell/gen-mapping': 0.3.2 jsesc: 2.5.2 - dev: true + dev: false - /@babel/generator@7.21.3: - resolution: {integrity: sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==} + /@babel/generator@7.21.4: + resolution: {integrity: sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.17 jsesc: 2.5.2 - dev: true /@babel/helper-annotate-as-pure@7.18.6: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 - dev: true + '@babel/types': 7.21.4 /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-explode-assignable-expression': 7.18.6 - '@babel/types': 7.20.7 - dev: true - - /@babel/helper-compilation-targets@7.20.0(@babel/core@7.21.3): - resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.20.1 - '@babel/core': 7.21.3 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - semver: 6.3.0 - dev: true + '@babel/types': 7.21.4 - /@babel/helper-compilation-targets@7.20.7(@babel/core@7.21.3): - resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} + /@babel/helper-compilation-targets@7.21.4(@babel/core@7.19.1): + resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.21.0 - '@babel/core': 7.21.3 + '@babel/compat-data': 7.21.4 + '@babel/core': 7.19.1 '@babel/helper-validator-option': 7.21.0 browserslist: 4.21.4 lru-cache: 5.1.1 semver: 6.3.0 - dev: true - - /@babel/helper-create-class-features-plugin@7.20.7(@babel/core@7.21.3): - resolution: {integrity: sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.21.3 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-member-expression-to-functions': 7.20.7 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-split-export-declaration': 7.18.6 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.21.3): - resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} + /@babel/helper-create-class-features-plugin@7.21.4(@babel/core@7.19.1): + resolution: {integrity: sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 @@ -2008,34 +1963,31 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 transitivePeerDependencies: - supports-color - dev: true - /@babel/helper-create-regexp-features-plugin@7.19.0(@babel/core@7.21.3): + /@babel/helper-create-regexp-features-plugin@7.19.0(@babel/core@7.19.1): resolution: {integrity: sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 regexpu-core: 5.2.1 - dev: true - /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.3): + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.19.1): resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.1 semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-environment-visitor@7.18.9: resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} @@ -2045,53 +1997,42 @@ packages: resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 - dev: true + '@babel/types': 7.21.4 /@babel/helper-function-name@7.19.0: resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-function-name@7.21.0: resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/types': 7.21.3 - dev: true + '@babel/types': 7.21.4 /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 - - /@babel/helper-member-expression-to-functions@7.20.7: - resolution: {integrity: sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.21.3 - dev: true + '@babel/types': 7.21.4 /@babel/helper-member-expression-to-functions@7.21.0: resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 - dev: true + '@babel/types': 7.21.4 /@babel/helper-module-imports@7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 - dev: true + '@babel/types': 7.21.4 - /@babel/helper-module-transforms@7.20.2: - resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} + /@babel/helper-module-transforms@7.19.0: + resolution: {integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 @@ -2100,11 +2041,10 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-module-transforms@7.21.2: resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} @@ -2116,72 +2056,75 @@ packages: '@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.20.7 - '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-optimise-call-expression@7.18.6: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 - dev: true + '@babel/types': 7.21.4 + + /@babel/helper-plugin-utils@7.19.0: + resolution: {integrity: sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==} + engines: {node: '>=6.9.0'} /@babel/helper-plugin-utils@7.20.2: resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.21.3): + /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-wrap-function': 7.19.0 - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-replace-supers@7.20.7: resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-member-expression-to-functions': 7.20.7 + '@babel/helper-member-expression-to-functions': 7.21.0 '@babel/helper-optimise-call-expression': 7.18.6 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color - dev: true /@babel/helper-simple-access@7.20.2: resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 - dev: true + '@babel/types': 7.21.4 + + /@babel/helper-skip-transparent-expression-wrappers@7.18.9: + resolution: {integrity: sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 /@babel/helper-skip-transparent-expression-wrappers@7.20.0: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 - dev: true + '@babel/types': 7.21.4 /@babel/helper-split-export-declaration@7.18.6: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-string-parser@7.19.4: resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} @@ -2194,12 +2137,10 @@ packages: /@babel/helper-validator-option@7.18.6: resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-option@7.21.0: resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-wrap-function@7.19.0: resolution: {integrity: sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==} @@ -2207,22 +2148,20 @@ packages: dependencies: '@babel/helper-function-name': 7.21.0 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.21.3 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color - dev: true - /@babel/helpers@7.21.0: - resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} + /@babel/helpers@7.19.0: + resolution: {integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color - dev: true /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} @@ -2237,477 +2176,433 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.20.2 + '@babel/types': 7.21.4 dev: false - /@babel/parser@7.20.3: - resolution: {integrity: sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.21.3 - - /@babel/parser@7.20.7: - resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} + /@babel/parser@7.19.1: + resolution: {integrity: sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 + dev: false - /@babel/parser@7.21.3: - resolution: {integrity: sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==} + /@babel/parser@7.21.4: + resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.21.3 - dev: true + '@babel/types': 7.21.4 - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.21.3): + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.18.9(@babel/core@7.21.3): + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) - dev: true + '@babel/helper-skip-transparent-expression-wrappers': 7.18.9 + '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.19.1) - /@babel/plugin-proposal-async-generator-functions@7.20.1(@babel/core@7.21.3): - resolution: {integrity: sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==} + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.19.1): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.19.1) transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-proposal-class-static-block@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-class-static-block@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.19.1) transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.21.3): + /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.19.1): resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.19.1) transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.19.1) - /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.3): + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.19.1) - /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.19.1) - /@babel/plugin-proposal-logical-assignment-operators@7.18.9(@babel/core@7.21.3): + /@babel/plugin-proposal-logical-assignment-operators@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.19.1) - /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.19.1) - /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.19.1) - /@babel/plugin-proposal-object-rest-spread@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==} + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.19.1): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.20.1 - '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/compat-data': 7.21.4 + '@babel/core': 7.19.1 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.19.1) - /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) - dev: true + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.19.1) - /@babel/plugin-proposal-optional-chaining@7.18.9(@babel/core@7.21.3): + /@babel/plugin-proposal-optional-chaining@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) - dev: true + '@babel/helper-skip-transparent-expression-wrappers': 7.18.9 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.19.1) - /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-proposal-private-property-in-object@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-private-property-in-object@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.19.1) transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.21.3): + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.3): + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.19.1): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.3): + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.19.1): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.3): + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.19.1): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.21.3): + /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.19.1): resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-plugin-utils': 7.20.2 - dev: true + '@babel/core': 7.19.1 + '@babel/helper-plugin-utils': 7.19.0 - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.21.3): + /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.19.1): resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.21.3): + /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.3): + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.19.1): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.3): + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.19.1): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.3): + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.19.1): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.3): + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.19.1): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.3): + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.19.1): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.21.3): - resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} + /@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.19.1): + resolution: {integrity: sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-arrow-functions@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-arrow-functions@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-async-to-generator@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-async-to-generator@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.19.1) transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-block-scoping@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==} + /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.19.1): + resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-classes@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==} + /@babel/plugin-transform-classes@7.21.0(@babel/core@7.19.1): + resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.1) '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-optimise-call-expression': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 @@ -2715,507 +2610,482 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-computed-properties@7.18.9(@babel/core@7.21.3): + /@babel/plugin-transform-computed-properties@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-destructuring@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==} + /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.19.1): + resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.21.3): + /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-for-of@7.18.8(@babel/core@7.21.3): + /@babel/plugin-transform-for-of@7.18.8(@babel/core@7.19.1): resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.21.3): + /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.1) '@babel/helper-function-name': 7.19.0 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-literals@7.18.9(@babel/core@7.21.3): + /@babel/plugin-transform-literals@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-modules-amd@7.19.6(@babel/core@7.21.3): - resolution: {integrity: sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==} + /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.19.1): + resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-module-transforms': 7.20.2 + '@babel/core': 7.19.1 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-modules-commonjs@7.19.6(@babel/core@7.21.3): - resolution: {integrity: sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==} + /@babel/plugin-transform-modules-commonjs@7.21.2(@babel/core@7.19.1): + resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-module-transforms': 7.20.2 + '@babel/core': 7.19.1 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-simple-access': 7.20.2 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-modules-systemjs@7.19.6(@babel/core@7.21.3): - resolution: {integrity: sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==} + /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.19.1): + resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-module-transforms': 7.20.2 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-identifier': 7.19.1 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-module-transforms': 7.20.2 + '@babel/core': 7.19.1 + '@babel/helper-module-transforms': 7.19.0 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-named-capturing-groups-regex@7.19.1(@babel/core@7.21.3): + /@babel/plugin-transform-named-capturing-groups-regex@7.19.1(@babel/core@7.19.1): resolution: {integrity: sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-parameters@7.20.3(@babel/core@7.21.3): - resolution: {integrity: sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==} + /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.19.1): + resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-react-jsx-development@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-react-jsx-development@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/plugin-transform-react-jsx': 7.19.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/plugin-transform-react-jsx': 7.19.0(@babel/core@7.19.1) dev: true - /@babel/plugin-transform-react-jsx@7.19.0(@babel/core@7.21.3): + /@babel/plugin-transform-react-jsx@7.19.0(@babel/core@7.19.1): resolution: {integrity: sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.21.3) - '@babel/types': 7.20.2 + '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.19.1) + '@babel/types': 7.21.4 dev: true - /@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-regenerator@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-regenerator@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 regenerator-transform: 0.15.0 - dev: true - /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-runtime@7.21.0(@babel/core@7.21.3): + /@babel/plugin-transform-runtime@7.21.0(@babel/core@7.19.1): resolution: {integrity: sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-module-imports': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) - babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) - babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.3) + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.19.1) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.19.1) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.19.1) semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-spread@7.19.0(@babel/core@7.21.3): + /@babel/plugin-transform-spread@7.19.0(@babel/core@7.19.1): resolution: {integrity: sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - dev: true + '@babel/helper-skip-transparent-expression-wrappers': 7.18.9 - /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.21.3): + /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.21.3): + /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.19.1): resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.21.3): + /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.19.1): resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-typescript': 7.20.0(@babel/core@7.21.3) + '@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.19.1) transitivePeerDependencies: - supports-color - dev: true - /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.21.3): + /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.19.1): resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.21.3): + /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 - dev: true - /@babel/preset-env@7.20.2(@babel/core@7.21.3): + /@babel/preset-env@7.20.2(@babel/core@7.19.1): resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.20.1 - '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/compat-data': 7.21.4 + '@babel/core': 7.19.1 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.1) '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-proposal-async-generator-functions': 7.20.1(@babel/core@7.21.3) - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-class-static-block': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-logical-assignment-operators': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-object-rest-spread': 7.20.2(@babel/core@7.21.3) - '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-private-property-in-object': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.3) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.21.3) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.3) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.3) - '@babel/plugin-transform-arrow-functions': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-async-to-generator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-block-scoping': 7.20.2(@babel/core@7.21.3) - '@babel/plugin-transform-classes': 7.20.2(@babel/core@7.21.3) - '@babel/plugin-transform-computed-properties': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-destructuring': 7.20.2(@babel/core@7.21.3) - '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-for-of': 7.18.8(@babel/core@7.21.3) - '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-amd': 7.19.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-commonjs': 7.19.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-systemjs': 7.19.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1(@babel/core@7.21.3) - '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) - '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-regenerator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-spread': 7.19.0(@babel/core@7.21.3) - '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.21.3) - '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.21.3) - '@babel/preset-modules': 0.1.5(@babel/core@7.21.3) - '@babel/types': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) - babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) - babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.3) - core-js-compat: 3.26.0 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.19.1) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-class-static-block': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-logical-assignment-operators': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.19.1) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-private-property-in-object': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.19.1) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.19.1) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.19.1) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.19.1) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.19.1) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.19.1) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.19.1) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.19.1) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.19.1) + '@babel/plugin-transform-arrow-functions': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-async-to-generator': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.19.1) + '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.19.1) + '@babel/plugin-transform-computed-properties': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.19.1) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-for-of': 7.18.8(@babel/core@7.19.1) + '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.19.1) + '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.19.1) + '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.19.1) + '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1(@babel/core@7.19.1) + '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.19.1) + '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-regenerator': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-spread': 7.19.0(@babel/core@7.19.1) + '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.19.1) + '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.19.1) + '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.19.1) + '@babel/preset-modules': 0.1.5(@babel/core@7.19.1) + '@babel/types': 7.21.4 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.19.1) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.19.1) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.19.1) + core-js-compat: 3.25.2 semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/preset-modules@0.1.5(@babel/core@7.21.3): + /@babel/preset-modules@0.1.5(@babel/core@7.19.1): resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) - '@babel/types': 7.20.2 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.19.1) + '@babel/types': 7.21.4 esutils: 2.0.3 - dev: true - /@babel/preset-react@7.18.6(@babel/core@7.21.3): + /@babel/preset-react@7.18.6(@babel/core@7.19.1): resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-react-jsx': 7.19.0(@babel/core@7.21.3) - '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-react-pure-annotations': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-react-jsx': 7.19.0(@babel/core@7.19.1) + '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.19.1) + '@babel/plugin-transform-react-pure-annotations': 7.18.6(@babel/core@7.19.1) dev: true - /@babel/preset-typescript@7.21.0(@babel/core@7.21.3): + /@babel/preset-typescript@7.21.0(@babel/core@7.19.1): resolution: {integrity: sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 + '@babel/core': 7.19.1 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.3) + '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.19.1) transitivePeerDependencies: - supports-color + + /@babel/runtime-corejs3@7.19.1: + resolution: {integrity: sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.25.2 + regenerator-runtime: 0.13.11 dev: true /@babel/runtime@7.21.0: @@ -3228,100 +3098,65 @@ packages: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.20.7 - '@babel/types': 7.21.3 - - /@babel/traverse@7.20.1: - resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.4 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.3 - '@babel/types': 7.20.2 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: false + '@babel/code-frame': 7.21.4 + '@babel/parser': 7.21.4 + '@babel/types': 7.21.4 - /@babel/traverse@7.20.1(supports-color@5.5.0): - resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} + /@babel/traverse@7.18.9(supports-color@5.5.0): + resolution: {integrity: sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.4 + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.3 - '@babel/types': 7.20.2 + '@babel/parser': 7.21.4 + '@babel/types': 7.21.4 debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/traverse@7.20.10: - resolution: {integrity: sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg==} + /@babel/traverse@7.19.1: + resolution: {integrity: sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.7 + '@babel/generator': 7.19.0 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.7 - '@babel/types': 7.21.3 - debug: 4.3.4 + '@babel/parser': 7.19.1 + '@babel/types': 7.21.4 + debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true + dev: false - /@babel/traverse@7.21.3: - resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} + /@babel/traverse@7.21.4: + resolution: {integrity: sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.21.3 + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.21.3 - '@babel/types': 7.21.3 - debug: 4.3.4 + '@babel/parser': 7.21.4 + '@babel/types': 7.21.4 + debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true - - /@babel/types@7.20.2: - resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - - /@babel/types@7.20.7: - resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - /@babel/types@7.21.3: - resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==} + /@babel/types@7.21.4: + resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.19.4 @@ -3522,16 +3357,16 @@ packages: resolution: {integrity: sha512-3lDltBqr41BZpJRidbXnKiWwvvfpb8CQ0SKEBW1XsnKTzP9ZcJnZuSoTizBxd6Hx2VPrGFooPjuh+ohQ3QIoHg==} dependencies: '@rollup/pluginutils': 4.2.1 - '@webcomponents/custom-elements': 1.5.1 + '@webcomponents/custom-elements': 1.5.0 acorn-walk: 8.2.0 cheerio: 1.0.0-rc.12 connect-injector: 0.4.4 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) es-module-lexer: 0.10.5 fast-glob: 3.2.12 fs-extra: 10.1.0 jsesc: 3.0.2 - magic-string: 0.26.7 + magic-string: 0.26.3 picocolors: 1.0.0 react-refresh: 0.13.0 rollup: 3.9.1 @@ -3540,14 +3375,14 @@ packages: - supports-color dev: true - /@emotion/is-prop-valid@1.2.0: - resolution: {integrity: sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==} + /@emotion/is-prop-valid@1.1.3: + resolution: {integrity: sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA==} dependencies: - '@emotion/memoize': 0.8.0 + '@emotion/memoize': 0.7.5 dev: true - /@emotion/memoize@0.8.0: - resolution: {integrity: sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==} + /@emotion/memoize@0.7.5: + resolution: {integrity: sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==} dev: true /@emotion/stylis@0.8.5: @@ -3558,125 +3393,127 @@ packages: resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} dev: true - /@esbuild-kit/cjs-loader@2.4.0: - resolution: {integrity: sha512-DBBCiHPgL2B/elUpvCDhNHXnlZQ9sfO2uyt1OJyAXKT41beQEFY4OxZ6gwS+ZesRCbZ6JV8M7GEyOPkjv8kdIw==} + /@esbuild-kit/cjs-loader@2.3.3: + resolution: {integrity: sha512-Rt4O1mXlPEDVxvjsHLgbtHVdUXYK9C1/6ThpQnt7FaXIjUOsI6qhHYMgALhNnlIMZffag44lXd6Dqgx3xALbpQ==} dependencies: - '@esbuild-kit/core-utils': 3.0.0 + '@esbuild-kit/core-utils': 2.3.0 get-tsconfig: 4.2.0 dev: true - /@esbuild-kit/core-utils@3.0.0: - resolution: {integrity: sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==} + /@esbuild-kit/core-utils@2.3.0: + resolution: {integrity: sha512-JL73zt/LN/qqziHuod4/bM2xBNNofDZu1cbwT6KIn6B11lA4cgDXkoSHOfNCbZMZOnh0Aqf0vW/gNQC+Z18hKQ==} dependencies: - esbuild: 0.15.13 + esbuild: 0.15.8 source-map-support: 0.5.21 dev: true - /@esbuild-kit/esm-loader@2.5.0: - resolution: {integrity: sha512-ySs0qOsiwj+hsgZM9/MniGdvfa9/WzqfFuIia8/5gSUPeIQIX2/tG91QakxPFOR35VFiwTB7wCiHtiS6dc6SkA==} + /@esbuild-kit/esm-loader@2.4.2: + resolution: {integrity: sha512-N9dPKAj8WOx6djVnStgILWXip4fjDcBk9L7azO0/uQDpu8Ee0eaL78mkN4Acid9BzvNAKWwdYXFJZnsVahNEew==} dependencies: - '@esbuild-kit/core-utils': 3.0.0 + '@esbuild-kit/core-utils': 2.3.0 get-tsconfig: 4.2.0 dev: true - /@esbuild-plugins/node-globals-polyfill@0.1.1(esbuild@0.17.12): + /@esbuild-plugins/node-globals-polyfill@0.1.1(esbuild@0.17.15): resolution: {integrity: sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==} peerDependencies: esbuild: '*' dependencies: - esbuild: 0.17.12 + esbuild: 0.17.15 - /@esbuild/android-arm64@0.17.12: - resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} + /@esbuild/android-arm64@0.17.15: + resolution: {integrity: sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==} engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true optional: true - /@esbuild/android-arm@0.15.13: - resolution: {integrity: sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==} + /@esbuild/android-arm@0.15.8: + resolution: {integrity: sha512-CyEWALmn+no/lbgbAJsbuuhT8s2J19EJGHkeyAwjbFJMrj80KJ9zuYsoAvidPTU7BgBf87r/sgae8Tw0dbOc4Q==} engines: {node: '>=12'} cpu: [arm] os: [android] requiresBuild: true + dependencies: + esbuild-wasm: 0.15.8 dev: true optional: true - /@esbuild/android-arm@0.17.12: - resolution: {integrity: sha512-E/sgkvwoIfj4aMAPL2e35VnUJspzVYl7+M1B2cqeubdBhADV4uPon0KCc8p2G+LqSJ6i8ocYPCqY3A4GGq0zkQ==} + /@esbuild/android-arm@0.17.15: + resolution: {integrity: sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==} engines: {node: '>=12'} cpu: [arm] os: [android] requiresBuild: true optional: true - /@esbuild/android-x64@0.17.12: - resolution: {integrity: sha512-m4OsaCr5gT+se25rFPHKQXARMyAehHTQAz4XX1Vk3d27VtqiX0ALMBPoXZsGaB6JYryCLfgGwUslMqTfqeLU0w==} + /@esbuild/android-x64@0.17.15: + resolution: {integrity: sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==} engines: {node: '>=12'} cpu: [x64] os: [android] requiresBuild: true optional: true - /@esbuild/darwin-arm64@0.17.12: - resolution: {integrity: sha512-O3GCZghRIx+RAN0NDPhyyhRgwa19MoKlzGonIb5hgTj78krqp9XZbYCvFr9N1eUxg0ZQEpiiZ4QvsOQwBpP+lg==} + /@esbuild/darwin-arm64@0.17.15: + resolution: {integrity: sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /@esbuild/darwin-x64@0.17.12: - resolution: {integrity: sha512-5D48jM3tW27h1qjaD9UNRuN+4v0zvksqZSPZqeSWggfMlsVdAhH3pwSfQIFJwcs9QJ9BRibPS4ViZgs3d2wsCA==} + /@esbuild/darwin-x64@0.17.15: + resolution: {integrity: sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==} engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /@esbuild/freebsd-arm64@0.17.12: - resolution: {integrity: sha512-OWvHzmLNTdF1erSvrfoEBGlN94IE6vCEaGEkEH29uo/VoONqPnoDFfShi41Ew+yKimx4vrmmAJEGNoyyP+OgOQ==} + /@esbuild/freebsd-arm64@0.17.15: + resolution: {integrity: sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true optional: true - /@esbuild/freebsd-x64@0.17.12: - resolution: {integrity: sha512-A0Xg5CZv8MU9xh4a+7NUpi5VHBKh1RaGJKqjxe4KG87X+mTjDE6ZvlJqpWoeJxgfXHT7IMP9tDFu7IZ03OtJAw==} + /@esbuild/freebsd-x64@0.17.15: + resolution: {integrity: sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true optional: true - /@esbuild/linux-arm64@0.17.12: - resolution: {integrity: sha512-cK3AjkEc+8v8YG02hYLQIQlOznW+v9N+OI9BAFuyqkfQFR+DnDLhEM5N8QRxAUz99cJTo1rLNXqRrvY15gbQUg==} + /@esbuild/linux-arm64@0.17.15: + resolution: {integrity: sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-arm@0.17.12: - resolution: {integrity: sha512-WsHyJ7b7vzHdJ1fv67Yf++2dz3D726oO3QCu8iNYik4fb5YuuReOI9OtA+n7Mk0xyQivNTPbl181s+5oZ38gyA==} + /@esbuild/linux-arm@0.17.15: + resolution: {integrity: sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==} engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ia32@0.17.12: - resolution: {integrity: sha512-jdOBXJqcgHlah/nYHnj3Hrnl9l63RjtQ4vn9+bohjQPI2QafASB5MtHAoEv0JQHVb/xYQTFOeuHnNYE1zF7tYw==} + /@esbuild/linux-ia32@0.17.15: + resolution: {integrity: sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==} engines: {node: '>=12'} cpu: [ia32] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-loong64@0.15.13: - resolution: {integrity: sha512-+BoyIm4I8uJmH/QDIH0fu7MG0AEx9OXEDXnqptXCwKOlOqZiS4iraH1Nr7/ObLMokW3sOCeBNyD68ATcV9b9Ag==} + /@esbuild/linux-loong64@0.15.8: + resolution: {integrity: sha512-pE5RQsOTSERCtfZdfCT25wzo7dfhOSlhAXcsZmuvRYhendOv7djcdvtINdnDp2DAjP17WXlBB4nBO6sHLczmsg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -3684,113 +3521,113 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.17.12: - resolution: {integrity: sha512-GTOEtj8h9qPKXCyiBBnHconSCV9LwFyx/gv3Phw0pa25qPYjVuuGZ4Dk14bGCfGX3qKF0+ceeQvwmtI+aYBbVA==} + /@esbuild/linux-loong64@0.17.15: + resolution: {integrity: sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.17.12: - resolution: {integrity: sha512-o8CIhfBwKcxmEENOH9RwmUejs5jFiNoDw7YgS0EJTF6kgPgcqLFjgoc5kDey5cMHRVCIWc6kK2ShUePOcc7RbA==} + /@esbuild/linux-mips64el@0.17.15: + resolution: {integrity: sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.17.12: - resolution: {integrity: sha512-biMLH6NR/GR4z+ap0oJYb877LdBpGac8KfZoEnDiBKd7MD/xt8eaw1SFfYRUeMVx519kVkAOL2GExdFmYnZx3A==} + /@esbuild/linux-ppc64@0.17.15: + resolution: {integrity: sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-riscv64@0.17.12: - resolution: {integrity: sha512-jkphYUiO38wZGeWlfIBMB72auOllNA2sLfiZPGDtOBb1ELN8lmqBrlMiucgL8awBw1zBXN69PmZM6g4yTX84TA==} + /@esbuild/linux-riscv64@0.17.15: + resolution: {integrity: sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-s390x@0.17.12: - resolution: {integrity: sha512-j3ucLdeY9HBcvODhCY4b+Ds3hWGO8t+SAidtmWu/ukfLLG/oYDMaA+dnugTVAg5fnUOGNbIYL9TOjhWgQB8W5g==} + /@esbuild/linux-s390x@0.17.15: + resolution: {integrity: sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true optional: true - /@esbuild/linux-x64@0.17.12: - resolution: {integrity: sha512-uo5JL3cgaEGotaqSaJdRfFNSCUJOIliKLnDGWaVCgIKkHxwhYMm95pfMbWZ9l7GeW9kDg0tSxcy9NYdEtjwwmA==} + /@esbuild/linux-x64@0.17.15: + resolution: {integrity: sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==} engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@esbuild/netbsd-x64@0.17.12: - resolution: {integrity: sha512-DNdoRg8JX+gGsbqt2gPgkgb00mqOgOO27KnrWZtdABl6yWTST30aibGJ6geBq3WM2TIeW6COs5AScnC7GwtGPg==} + /@esbuild/netbsd-x64@0.17.15: + resolution: {integrity: sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true optional: true - /@esbuild/openbsd-x64@0.17.12: - resolution: {integrity: sha512-aVsENlr7B64w8I1lhHShND5o8cW6sB9n9MUtLumFlPhG3elhNWtE7M1TFpj3m7lT3sKQUMkGFjTQBrvDDO1YWA==} + /@esbuild/openbsd-x64@0.17.15: + resolution: {integrity: sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true optional: true - /@esbuild/sunos-x64@0.17.12: - resolution: {integrity: sha512-qbHGVQdKSwi0JQJuZznS4SyY27tYXYF0mrgthbxXrZI3AHKuRvU+Eqbg/F0rmLDpW/jkIZBlCO1XfHUBMNJ1pg==} + /@esbuild/sunos-x64@0.17.15: + resolution: {integrity: sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true optional: true - /@esbuild/win32-arm64@0.17.12: - resolution: {integrity: sha512-zsCp8Ql+96xXTVTmm6ffvoTSZSV2B/LzzkUXAY33F/76EajNw1m+jZ9zPfNJlJ3Rh4EzOszNDHsmG/fZOhtqDg==} + /@esbuild/win32-arm64@0.17.15: + resolution: {integrity: sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==} engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /@esbuild/win32-ia32@0.17.12: - resolution: {integrity: sha512-FfrFjR4id7wcFYOdqbDfDET3tjxCozUgbqdkOABsSFzoZGFC92UK7mg4JKRc/B3NNEf1s2WHxJ7VfTdVDPN3ng==} + /@esbuild/win32-ia32@0.17.15: + resolution: {integrity: sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /@esbuild/win32-x64@0.17.12: - resolution: {integrity: sha512-JOOxw49BVZx2/5tW3FqkdjSD/5gXYeVGPDcB0lvap0gLQshkh1Nyel1QazC+wNxus3xPlsYAgqU1BUmrmCvWtw==} + /@esbuild/win32-x64@0.17.15: + resolution: {integrity: sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==} engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true optional: true - /@eslint-community/eslint-utils@4.3.0(eslint@8.36.0): - resolution: {integrity: sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==} + /@eslint-community/eslint-utils@4.4.0(eslint@8.36.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: eslint: 8.36.0 - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.0 - /@eslint-community/regexpp@4.4.0: - resolution: {integrity: sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==} + /@eslint-community/regexpp@4.5.0: + resolution: {integrity: sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} /@eslint/eslintrc@1.4.1: @@ -3798,9 +3635,9 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 - espree: 9.4.1 - globals: 13.19.0 + debug: 4.3.4(supports-color@5.5.0) + espree: 9.5.1 + globals: 13.20.0 ignore: 5.2.0 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -3810,14 +3647,14 @@ packages: - supports-color dev: false - /@eslint/eslintrc@2.0.1: - resolution: {integrity: sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==} + /@eslint/eslintrc@2.0.2: + resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 - espree: 9.5.0 - globals: 13.19.0 + debug: 4.3.4(supports-color@5.5.0) + espree: 9.5.1 + globals: 13.20.0 ignore: 5.2.0 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -3830,8 +3667,8 @@ packages: resolution: {integrity: sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@faker-js/faker@7.6.0: - resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} + /@faker-js/faker@7.5.0: + resolution: {integrity: sha512-8wNUCCUHvfvI0gQpDUho/3gPzABffnCn5um65F8dzQ86zz6dlt4+nmAA7PQUc8L+eH+9RgR/qzy5N/8kN0Ozdw==} engines: {node: '>=14.0.0', npm: '>=6.0.0'} dev: false @@ -3840,7 +3677,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -3858,7 +3695,6 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.14 - dev: true /@jridgewell/gen-mapping@0.3.2: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} @@ -3866,7 +3702,7 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/trace-mapping': 0.3.15 /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} @@ -3879,6 +3715,12 @@ packages: /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + /@jridgewell/trace-mapping@0.3.15: + resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + /@jridgewell/trace-mapping@0.3.17: resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} dependencies: @@ -3946,9 +3788,8 @@ packages: /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} - dev: true - /@rollup/plugin-commonjs@24.0.0: + /@rollup/plugin-commonjs@24.0.0(rollup@3.9.1): resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} engines: {node: '>=14.0.0'} peerDependencies: @@ -3957,64 +3798,30 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2 + '@rollup/pluginutils': 5.0.2(rollup@3.9.1) commondir: 1.0.1 estree-walker: 2.0.2 - glob: 8.0.3 + glob: 8.1.0 is-reference: 1.2.1 magic-string: 0.27.0 + rollup: 3.9.1 dev: false - /@rollup/plugin-commonjs@24.0.0(rollup@3.9.1): - resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} + /@rollup/plugin-inject@5.0.3(rollup@3.9.1): + resolution: {integrity: sha512-411QlbL+z2yXpRWFXSmw/teQRMkXcAAC8aYTemc15gwJRpvEVDQwoe+N/HTFD8RFG8+88Bme9DK2V9CVm7hJdA==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.68.0||^3.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0 peerDependenciesMeta: rollup: optional: true dependencies: '@rollup/pluginutils': 5.0.2(rollup@3.9.1) - commondir: 1.0.1 estree-walker: 2.0.2 - glob: 8.0.3 - is-reference: 1.2.1 magic-string: 0.27.0 rollup: 3.9.1 dev: false - /@rollup/plugin-inject@5.0.2(rollup@3.9.1): - resolution: {integrity: sha512-zRthPC/sZ2OaQwPh2LvFn0A+3SyMAZR1Vqsp89mWkIuGXKswT8ty1JWj1pf7xdZvft4gHZaCuhdopuiCwjclWg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.9.1) - estree-walker: 2.0.2 - magic-string: 0.26.7 - rollup: 3.9.1 - dev: false - - /@rollup/plugin-node-resolve@15.0.1: - resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.0.2 - '@types/resolve': 1.20.2 - deepmerge: 4.2.2 - is-builtin-module: 3.2.0 - is-module: 1.0.0 - resolve: 1.22.1 - dev: false - /@rollup/plugin-node-resolve@15.0.1(rollup@3.9.1): resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} @@ -4040,20 +3847,6 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 - /@rollup/pluginutils@5.0.2: - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.0 - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: false - /@rollup/pluginutils@5.0.2(rollup@3.9.1): resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} @@ -4069,12 +3862,12 @@ packages: rollup: 3.9.1 dev: false - /@shopify/polaris-icons@6.7.0: - resolution: {integrity: sha512-4tlMQvZlaTvp4uYWo5zZq7NSvD1IIxS13/anRWXwcCD/HPLj7wnyYfwveHQOwo1iyrVV4Z2+hTJYTFVe3CBR0g==} + /@shopify/polaris-icons@6.12.0: + resolution: {integrity: sha512-KRIC5OUxLjJifqt//fslbRhfTrzBdnYH5sEuJ39fAHwnGQY+o9JnrZyJ2OIiTTRU9OQBgkhMwr1OaisJHMyWcA==} dev: true - /@shopify/polaris-tokens@6.3.0: - resolution: {integrity: sha512-ZYcV/yzTDw/qizqb2zKYi0ryNTWg1fKs492sZajs5Rk6TdEYIJSuIHG4U1iP2RFadIFWyHu5ELC5UZWsUCxP9w==} + /@shopify/polaris-tokens@6.8.1: + resolution: {integrity: sha512-KtLFlYQqomK82/A+yPorxj2lydzOQ9T29LyfcpOn5y5lVHmKie5k9RauEJjjRTA08BVVc16BctB32lCgjTnjsA==} dev: true /@shopify/polaris@10.16.1(react-dom@18.2.0)(react@18.2.0): @@ -4083,29 +3876,15 @@ packages: react: '*' react-dom: '*' dependencies: - '@shopify/polaris-icons': 6.7.0 - '@shopify/polaris-tokens': 6.3.0 - '@types/react': 18.0.26 + '@shopify/polaris-icons': 6.12.0 + '@shopify/polaris-tokens': 6.8.1 + '@types/react': 18.0.28 '@types/react-dom': 18.0.10 '@types/react-transition-group': 4.4.5 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-fast-compare: 3.2.0 - react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) - dev: true - - /@testing-library/dom@8.19.0: - resolution: {integrity: sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==} - engines: {node: '>=12'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/runtime': 7.21.0 - '@types/aria-query': 4.2.2 - aria-query: 5.1.3 - chalk: 4.1.2 - dom-accessibility-api: 0.5.14 - lz-string: 1.5.0 - pretty-format: 27.5.1 + react-transition-group: 4.4.2(react-dom@18.2.0)(react@18.2.0) dev: true /@testing-library/dom@8.19.1: @@ -4115,21 +3894,20 @@ packages: '@babel/code-frame': 7.18.6 '@babel/runtime': 7.21.0 '@types/aria-query': 5.0.1 - aria-query: 5.1.3 + aria-query: 5.0.0 chalk: 4.1.2 dom-accessibility-api: 0.5.14 lz-string: 1.4.4 pretty-format: 27.5.1 - dev: false - /@testing-library/dom@9.0.1: - resolution: {integrity: sha512-fTOVsMY9QLFCCXRHG3Ese6cMH5qIWwSbgxZsgeF5TNsy81HKaZ4kgehnSF8FsR3OF+numlIV2YcU79MzbnhSig==} + /@testing-library/dom@9.2.0: + resolution: {integrity: sha512-xTEnpUKiV/bMyEsE5bT4oYA0x0Z/colMtxzUY8bKyPXBNLn/e0V4ZjBZkEhms0xE4pv9QsPfSRu9AWS4y5wGvA==} engines: {node: '>=14'} dependencies: '@babel/code-frame': 7.18.6 '@babel/runtime': 7.21.0 '@types/aria-query': 5.0.1 - aria-query: 5.1.3 + aria-query: 5.0.0 chalk: 4.1.2 dom-accessibility-api: 0.5.14 lz-string: 1.5.0 @@ -4154,7 +3932,7 @@ packages: react-dom: '*' dependencies: '@babel/runtime': 7.21.0 - '@testing-library/dom': 8.19.0 + '@testing-library/dom': 8.19.1 '@types/react-dom': 18.0.10 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -4168,7 +3946,7 @@ packages: react-dom: '*' dependencies: '@babel/runtime': 7.21.0 - '@testing-library/dom': 9.0.1 + '@testing-library/dom': 9.2.0 '@types/react-dom': 18.0.10 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -4183,10 +3961,6 @@ packages: engines: {node: '>=10.13.0'} dev: false - /@types/aria-query@4.2.2: - resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} - dev: true - /@types/aria-query@5.0.1: resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} @@ -4224,7 +3998,7 @@ packages: /@types/is-ci@3.0.0: resolution: {integrity: sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==} dependencies: - ci-info: 3.5.0 + ci-info: 3.4.0 dev: true /@types/json-schema@7.0.11: @@ -4271,13 +4045,13 @@ packages: /@types/react-dom@18.0.10: resolution: {integrity: sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==} dependencies: - '@types/react': 18.0.26 + '@types/react': 18.0.28 dev: true /@types/react-portal@4.0.4: resolution: {integrity: sha512-ecVWngYHeSymq5XdrQOXRpIb9ay5SM4Stm/ur6+wc0Z+r05gafZ5SuMRbXKYsj4exNJa+4CTKK6J7qcTKm9K5g==} dependencies: - '@types/react': 18.0.26 + '@types/react': 18.0.28 dev: true /@types/react-transition-group@4.4.5: @@ -4286,20 +4060,12 @@ packages: '@types/react': 18.0.28 dev: true - /@types/react@18.0.26: - resolution: {integrity: sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.2 - csstype: 3.1.1 - dev: true - /@types/react@18.0.28: resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==} dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.2 - csstype: 3.1.1 + csstype: 3.1.0 dev: true /@types/resolve@1.20.2: @@ -4314,8 +4080,8 @@ packages: resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} dev: true - /@types/semver@7.3.13: - resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} + /@types/semver@7.3.12: + resolution: {integrity: sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==} /@types/shelljs@0.8.11: resolution: {integrity: sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==} @@ -4330,12 +4096,12 @@ packages: '@types/node': 18.15.5 dev: true - /@types/styled-components@5.1.26: - resolution: {integrity: sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==} + /@types/styled-components@5.1.25: + resolution: {integrity: sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ==} dependencies: '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 18.0.26 - csstype: 3.1.1 + '@types/react': 18.0.28 + csstype: 3.1.0 dev: true /@types/ua-parser-js@0.7.36: @@ -4357,17 +4123,17 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.4.0 + '@eslint-community/regexpp': 4.5.0 '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/type-utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) '@typescript-eslint/utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) eslint: 8.36.0 grapheme-splitter: 1.0.4 ignore: 5.2.0 natural-compare-lite: 1.4.0 - semver: 7.3.8 + semver: 7.3.7 tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: @@ -4386,7 +4152,7 @@ packages: '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/types': 5.56.0 '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) eslint: 8.36.0 typescript: 5.0.2 transitivePeerDependencies: @@ -4411,7 +4177,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) '@typescript-eslint/utils': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) eslint: 8.36.0 tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 @@ -4433,10 +4199,10 @@ packages: dependencies: '@typescript-eslint/types': 5.56.0 '@typescript-eslint/visitor-keys': 5.56.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 + semver: 7.3.7 tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: @@ -4448,15 +4214,15 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.3.0(eslint@8.36.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.36.0) '@types/json-schema': 7.0.11 - '@types/semver': 7.3.13 + '@types/semver': 7.3.12 '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/types': 5.56.0 '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) eslint: 8.36.0 eslint-scope: 5.1.1 - semver: 7.3.8 + semver: 7.3.7 transitivePeerDependencies: - supports-color - typescript @@ -4466,14 +4232,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.56.0 - eslint-visitor-keys: 3.3.0 - - /@vitest/expect@0.29.7: - resolution: {integrity: sha512-UtG0tW0DP6b3N8aw7PHmweKDsvPv4wjGvrVZW7OSxaFg76ShtVdMiMcUkZJgCE8QWUmhwaM0aQhbbVLo4F4pkA==} - dependencies: - '@vitest/spy': 0.29.7 - '@vitest/utils': 0.29.7 - chai: 4.3.7 + eslint-visitor-keys: 3.4.0 /@vitest/expect@0.29.8: resolution: {integrity: sha512-xlcVXn5I5oTq6NiZSY3ykyWixBxr5mG8HYtjvpgg6KaqHm0mvhX18xuwl5YGxIRNt/A5jidd7CWcNHrSvgaQqQ==} @@ -4481,14 +4240,6 @@ packages: '@vitest/spy': 0.29.8 '@vitest/utils': 0.29.8 chai: 4.3.7 - dev: true - - /@vitest/runner@0.29.7: - resolution: {integrity: sha512-Yt0+csM945+odOx4rjZSjibQfl2ymxqVsmYz6sO2fiO5RGPYDFCo60JF6tLL9pz4G/kjY4irUxadeB1XT+H1jg==} - dependencies: - '@vitest/utils': 0.29.7 - p-limit: 4.0.0 - pathe: 1.1.0 /@vitest/runner@0.29.8: resolution: {integrity: sha512-FzdhnRDwEr/A3Oo1jtIk/B952BBvP32n1ObMEb23oEJNO+qO5cBet6M2XWIDQmA7BDKGKvmhUf2naXyp/2JEwQ==} @@ -4496,26 +4247,15 @@ packages: '@vitest/utils': 0.29.8 p-limit: 4.0.0 pathe: 1.1.0 - dev: true - - /@vitest/spy@0.29.7: - resolution: {integrity: sha512-IalL0iO6A6Xz8hthR8sctk6ZS//zVBX48EiNwQguYACdgdei9ZhwMaBFV70mpmeYAFCRAm+DpoFHM5470Im78A==} - dependencies: - tinyspy: 1.0.2 /@vitest/spy@0.29.8: resolution: {integrity: sha512-VdjBe9w34vOMl5I5mYEzNX8inTxrZ+tYUVk9jxaZJmHFwmDFC/GV3KBFTA/JKswr3XHvZL+FE/yq5EVhb6pSAw==} dependencies: tinyspy: 1.0.2 - dev: true - /@vitest/ui@0.29.7: - resolution: {integrity: sha512-KeOztcAldlFU5i8DKCQcmGrih1dVowurZy/9iPz5JyQdPJzej+nW1nI4nYvc4ZmUtA8+IAe9uViqnU7IXc1RNw==} + /@vitest/ui@0.23.4: + resolution: {integrity: sha512-lNZVTTrkHThGAwNQ1ah1qCNnm70r7OLB5LCUdSqboStve/1eKTrtt27QfDSSUTG8AVJQzU0eaN/j8UocH+CqfA==} dependencies: - fast-glob: 3.2.12 - flatted: 3.2.7 - pathe: 1.1.0 - picocolors: 1.0.0 sirv: 2.0.2 dev: true @@ -4527,15 +4267,6 @@ packages: pathe: 1.1.0 picocolors: 1.0.0 sirv: 2.0.2 - dev: true - - /@vitest/utils@0.29.7: - resolution: {integrity: sha512-vNgGadp2eE5XKCXtZXL5UyNEDn68npSct75OC9AlELenSK0DiV1Mb9tfkwJHKjRb69iek+e79iipoJx8+s3SdA==} - dependencies: - cli-truncate: 3.1.0 - diff: 5.1.0 - loupe: 2.3.6 - pretty-format: 27.5.1 /@vitest/utils@0.29.8: resolution: {integrity: sha512-qGzuf3vrTbnoY+RjjVVIBYfuWMjn3UMUqyQtdGNZ6ZIIyte7B37exj6LaVkrZiUTvzSadVvO/tJm8AEgbGCBPg==} @@ -4544,62 +4275,61 @@ packages: diff: 5.1.0 loupe: 2.3.6 pretty-format: 27.5.1 - dev: true - /@vue/compiler-core@3.2.41: - resolution: {integrity: sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==} + /@vue/compiler-core@3.2.39: + resolution: {integrity: sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==} dependencies: - '@babel/parser': 7.20.3 - '@vue/shared': 3.2.41 + '@babel/parser': 7.21.4 + '@vue/shared': 3.2.39 estree-walker: 2.0.2 source-map: 0.6.1 dev: false - /@vue/compiler-dom@3.2.41: - resolution: {integrity: sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==} + /@vue/compiler-dom@3.2.39: + resolution: {integrity: sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==} dependencies: - '@vue/compiler-core': 3.2.41 - '@vue/shared': 3.2.41 + '@vue/compiler-core': 3.2.39 + '@vue/shared': 3.2.39 dev: false - /@vue/compiler-sfc@3.2.41: - resolution: {integrity: sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==} + /@vue/compiler-sfc@3.2.39: + resolution: {integrity: sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==} dependencies: - '@babel/parser': 7.20.3 - '@vue/compiler-core': 3.2.41 - '@vue/compiler-dom': 3.2.41 - '@vue/compiler-ssr': 3.2.41 - '@vue/reactivity-transform': 3.2.41 - '@vue/shared': 3.2.41 + '@babel/parser': 7.19.1 + '@vue/compiler-core': 3.2.39 + '@vue/compiler-dom': 3.2.39 + '@vue/compiler-ssr': 3.2.39 + '@vue/reactivity-transform': 3.2.39 + '@vue/shared': 3.2.39 estree-walker: 2.0.2 magic-string: 0.25.9 postcss: 8.4.20 source-map: 0.6.1 dev: false - /@vue/compiler-ssr@3.2.41: - resolution: {integrity: sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==} + /@vue/compiler-ssr@3.2.39: + resolution: {integrity: sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==} dependencies: - '@vue/compiler-dom': 3.2.41 - '@vue/shared': 3.2.41 + '@vue/compiler-dom': 3.2.39 + '@vue/shared': 3.2.39 dev: false - /@vue/reactivity-transform@3.2.41: - resolution: {integrity: sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==} + /@vue/reactivity-transform@3.2.39: + resolution: {integrity: sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==} dependencies: - '@babel/parser': 7.20.3 - '@vue/compiler-core': 3.2.41 - '@vue/shared': 3.2.41 + '@babel/parser': 7.21.4 + '@vue/compiler-core': 3.2.39 + '@vue/shared': 3.2.39 estree-walker: 2.0.2 magic-string: 0.25.9 dev: false - /@vue/shared@3.2.41: - resolution: {integrity: sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==} + /@vue/shared@3.2.39: + resolution: {integrity: sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==} dev: false - /@webcomponents/custom-elements@1.5.1: - resolution: {integrity: sha512-6T/XT3S1UHDlRWFSxRXdeSoYWczEl78sygNPS7jDyHVrfZcF/pUtWGYgxF4uviH59iPVw1eOWbhubm8CqO0MpA==} + /@webcomponents/custom-elements@1.5.0: + resolution: {integrity: sha512-c+7jPQCs9h/BYVcZ2Kna/3tsl3A/9EyXfvWjp5RiTDm1OpTcbZaCa1z4RNcTe/hUtXaqn64JjNW1yrWT+rZ8gg==} dev: true /@wessberg/stringutil@1.0.19: @@ -4627,11 +4357,6 @@ packages: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} - /acorn@8.8.1: - resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} - engines: {node: '>=0.4.0'} - hasBin: true - /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} @@ -4641,7 +4366,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -4709,10 +4434,23 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - /aria-query@5.1.3: - resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + /aria-query@4.2.2: + resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} + engines: {node: '>=6.0'} dependencies: - deep-equal: 2.2.0 + '@babel/runtime': 7.21.0 + '@babel/runtime-corejs3': 7.19.1 + dev: true + + /aria-query@5.0.0: + resolution: {integrity: sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==} + engines: {node: '>=6.0'} + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 /array-differ@3.0.0: resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==} @@ -4724,9 +4462,9 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 - get-intrinsic: 1.2.0 + define-properties: 1.1.4 + es-abstract: 1.21.2 + get-intrinsic: 1.1.3 is-string: 1.0.7 /array-union@2.1.0: @@ -4738,8 +4476,8 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 es-shim-unscopables: 1.0.0 /array.prototype.flatmap@1.3.1: @@ -4747,20 +4485,10 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 es-shim-unscopables: 1.0.0 - /array.prototype.tosorted@1.1.1: - resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.0 - dev: true - /arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} @@ -4791,63 +4519,58 @@ packages: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} - /axe-core@4.6.3: - resolution: {integrity: sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==} + /axe-core@4.4.3: + resolution: {integrity: sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==} engines: {node: '>=4'} dev: true /axios@1.2.2: resolution: {integrity: sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.1 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - /axobject-query@3.1.1: - resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} - dependencies: - deep-equal: 2.2.0 + /axobject-query@2.2.0: + resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} dev: true - /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.21.3): + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.19.1): resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.20.1 - '@babel/core': 7.21.3 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) + '@babel/compat-data': 7.21.4 + '@babel/core': 7.19.1 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.19.1) semver: 6.3.0 transitivePeerDependencies: - supports-color - dev: true - /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.21.3): + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.19.1): resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) - core-js-compat: 3.26.0 + '@babel/core': 7.19.1 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.19.1) + core-js-compat: 3.25.2 transitivePeerDependencies: - supports-color - dev: true - /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.21.3): + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.19.1): resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.21.3 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) + '@babel/core': 7.19.1 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.19.1) transitivePeerDependencies: - supports-color - dev: true - /babel-plugin-styled-components@2.0.7(styled-components@5.3.6): + /babel-plugin-styled-components@2.0.7(styled-components@5.3.5): resolution: {integrity: sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==} peerDependencies: styled-components: '>= 2' @@ -4857,7 +4580,7 @@ packages: babel-plugin-syntax-jsx: 6.18.0 lodash: 4.17.21 picomatch: 2.3.1 - styled-components: 5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) + styled-components: 5.3.5(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0) dev: true /babel-plugin-syntax-jsx@6.18.0: @@ -4916,14 +4639,14 @@ packages: dependencies: '@mdn/browser-compat-data': 4.2.1 '@types/object-path': 0.11.1 - '@types/semver': 7.3.13 + '@types/semver': 7.3.12 '@types/ua-parser-js': 0.7.36 browserslist: 4.20.2 - caniuse-lite: 1.0.30001431 + caniuse-lite: 1.0.30001400 isbot: 3.4.5 object-path: 0.11.8 - semver: 7.3.8 - ua-parser-js: 1.0.32 + semver: 7.3.7 + ua-parser-js: 1.0.2 dev: false /browserslist@4.20.2: @@ -4931,8 +4654,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001431 - electron-to-chromium: 1.4.284 + caniuse-lite: 1.0.30001400 + electron-to-chromium: 1.4.251 escalade: 3.1.1 node-releases: 2.0.6 picocolors: 1.0.0 @@ -4943,10 +4666,10 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001431 - electron-to-chromium: 1.4.284 + caniuse-lite: 1.0.30001400 + electron-to-chromium: 1.4.251 node-releases: 2.0.6 - update-browserslist-db: 1.0.10(browserslist@4.21.4) + update-browserslist-db: 1.0.9(browserslist@4.21.4) /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -4972,7 +4695,7 @@ packages: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 - get-intrinsic: 1.2.0 + get-intrinsic: 1.1.3 /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -4997,21 +4720,21 @@ packages: engines: {node: '>=10'} dev: false - /camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + /camelize@1.0.0: + resolution: {integrity: sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==} dev: true /caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: browserslist: 4.21.4 - caniuse-lite: 1.0.30001431 + caniuse-lite: 1.0.30001400 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: false - /caniuse-lite@1.0.30001431: - resolution: {integrity: sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==} + /caniuse-lite@1.0.30001400: + resolution: {integrity: sha512-Mv659Hn65Z4LgZdJ7ge5JTVbE3rqbJaaXgW5LEI9/tOaXclfIZ8DW7D7FCWWWmWiiPS7AC48S8kf3DApSxQdgA==} /chai@4.3.7: resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} @@ -5019,9 +4742,9 @@ packages: dependencies: assertion-error: 1.1.0 check-error: 1.0.2 - deep-eql: 4.1.2 + deep-eql: 4.1.3 get-func-name: 2.0.0 - loupe: 2.3.6 + loupe: 2.3.4 pathval: 1.1.1 type-detect: 4.0.8 @@ -5098,8 +4821,8 @@ packages: resolution: {integrity: sha512-A267cwetV1ninoID9ox6DPfqKbThHMV28sR1jy/Dog0MxxIQpkJqtUqcpQS+D/8pCDOtAB17pfywstKkaeuMEw==} dev: true - /ci-info@3.5.0: - resolution: {integrity: sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==} + /ci-info@3.4.0: + resolution: {integrity: sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==} dev: true /cli-table3@0.6.3: @@ -5132,15 +4855,6 @@ packages: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -5178,8 +4892,8 @@ packages: engines: {node: '>= 10'} dev: false - /commander@9.4.1: - resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} + /commander@9.4.0: + resolution: {integrity: sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==} engines: {node: ^12.20.0 || >=14} dev: false @@ -5198,7 +4912,7 @@ packages: dev: false /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} /concat-with-sourcemaps@1.1.0: resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} @@ -5227,14 +4941,19 @@ packages: - supports-color dev: true - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true + /convert-source-map@1.8.0: + resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} + dependencies: + safe-buffer: 5.1.2 - /core-js-compat@3.26.0: - resolution: {integrity: sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==} + /core-js-compat@3.25.2: + resolution: {integrity: sha512-TxfyECD4smdn3/CjWxczVtJqVLEEC2up7/82t7vC0AzNogr+4nQ8vyF7abxAuTXWvjTClSbvGhU0RgqA4ToQaQ==} dependencies: browserslist: 4.21.4 + + /core-js-pure@3.25.2: + resolution: {integrity: sha512-ItD7YpW1cUB4jaqFLZXe1AXkyqIxz6GqPnsDV4uF4hVcWh/WAGIqSqw5p0/WdsILM0Xht9s3Koyw05R3K6RtiA==} + requiresBuild: true dev: true /cosmiconfig@7.0.1: @@ -5308,7 +5027,7 @@ packages: /css-to-react-native@3.0.0: resolution: {integrity: sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==} dependencies: - camelize: 1.0.1 + camelize: 1.0.0 css-color-keywords: 1.0.0 postcss-value-parser: 4.2.0 dev: true @@ -5327,7 +5046,6 @@ packages: /css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - dev: true /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -5335,8 +5053,8 @@ packages: hasBin: true dev: false - /cssnano-preset-default@5.2.13(postcss@8.4.20): - resolution: {integrity: sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==} + /cssnano-preset-default@5.2.12(postcss@8.4.20): + resolution: {integrity: sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -5346,16 +5064,16 @@ packages: postcss: 8.4.20 postcss-calc: 8.2.4(postcss@8.4.20) postcss-colormin: 5.3.0(postcss@8.4.20) - postcss-convert-values: 5.1.3(postcss@8.4.20) + postcss-convert-values: 5.1.2(postcss@8.4.20) postcss-discard-comments: 5.1.2(postcss@8.4.20) postcss-discard-duplicates: 5.1.0(postcss@8.4.20) postcss-discard-empty: 5.1.1(postcss@8.4.20) postcss-discard-overridden: 5.1.0(postcss@8.4.20) - postcss-merge-longhand: 5.1.7(postcss@8.4.20) - postcss-merge-rules: 5.1.3(postcss@8.4.20) + postcss-merge-longhand: 5.1.6(postcss@8.4.20) + postcss-merge-rules: 5.1.2(postcss@8.4.20) postcss-minify-font-values: 5.1.0(postcss@8.4.20) postcss-minify-gradients: 5.1.1(postcss@8.4.20) - postcss-minify-params: 5.1.4(postcss@8.4.20) + postcss-minify-params: 5.1.3(postcss@8.4.20) postcss-minify-selectors: 5.2.1(postcss@8.4.20) postcss-normalize-charset: 5.1.0(postcss@8.4.20) postcss-normalize-display-values: 5.1.0(postcss@8.4.20) @@ -5363,11 +5081,11 @@ packages: postcss-normalize-repeat-style: 5.1.1(postcss@8.4.20) postcss-normalize-string: 5.1.0(postcss@8.4.20) postcss-normalize-timing-functions: 5.1.0(postcss@8.4.20) - postcss-normalize-unicode: 5.1.1(postcss@8.4.20) + postcss-normalize-unicode: 5.1.0(postcss@8.4.20) postcss-normalize-url: 5.1.0(postcss@8.4.20) postcss-normalize-whitespace: 5.1.1(postcss@8.4.20) postcss-ordered-values: 5.1.3(postcss@8.4.20) - postcss-reduce-initial: 5.1.1(postcss@8.4.20) + postcss-reduce-initial: 5.1.0(postcss@8.4.20) postcss-reduce-transforms: 5.1.0(postcss@8.4.20) postcss-svgo: 5.1.0(postcss@8.4.20) postcss-unique-selectors: 5.1.1(postcss@8.4.20) @@ -5382,13 +5100,13 @@ packages: postcss: 8.4.20 dev: false - /cssnano@5.1.14(postcss@8.4.20): - resolution: {integrity: sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==} + /cssnano@5.1.13(postcss@8.4.20): + resolution: {integrity: sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: - cssnano-preset-default: 5.2.13(postcss@8.4.20) + cssnano-preset-default: 5.2.12(postcss@8.4.20) lilconfig: 2.0.6 postcss: 8.4.20 yaml: 1.10.2 @@ -5419,8 +5137,8 @@ packages: dependencies: rrweb-cssom: 0.6.0 - /csstype@3.1.1: - resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} + /csstype@3.1.0: + resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==} dev: true /csv-generate@3.4.3: @@ -5490,17 +5208,6 @@ packages: dependencies: ms: 2.1.3 - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - /debug@4.3.4(supports-color@5.5.0): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -5512,10 +5219,9 @@ packages: dependencies: ms: 2.1.2 supports-color: 5.5.0 - dev: true - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + /decamelize-keys@1.1.0: + resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} engines: {node: '>=0.10.0'} dependencies: decamelize: 1.2.0 @@ -5527,39 +5233,15 @@ packages: engines: {node: '>=0.10.0'} dev: true - /decimal.js@10.4.2: - resolution: {integrity: sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==} - /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - /deep-eql@4.1.2: - resolution: {integrity: sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==} + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} dependencies: type-detect: 4.0.8 - /deep-equal@2.2.0: - resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} - dependencies: - call-bind: 1.0.2 - es-get-iterator: 1.1.3 - get-intrinsic: 1.2.0 - is-arguments: 1.1.1 - is-array-buffer: 3.0.2 - is-date-object: 1.0.5 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - isarray: 2.0.5 - object-is: 1.1.5 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.4.3 - side-channel: 1.0.4 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.9 - /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -5568,8 +5250,8 @@ packages: engines: {node: '>=0.10.0'} dev: false - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + /defaults@1.0.3: + resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} dependencies: clone: 1.0.4 dev: true @@ -5578,8 +5260,8 @@ packages: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} - /define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + /define-properties@1.1.4: + resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} engines: {node: '>= 0.4'} dependencies: has-property-descriptors: 1.0.0 @@ -5595,11 +5277,11 @@ packages: hasBin: true dependencies: '@babel/parser': 7.16.4 - '@babel/traverse': 7.20.1 - '@vue/compiler-sfc': 3.2.41 + '@babel/traverse': 7.19.1 + '@vue/compiler-sfc': 3.2.39 camelcase: 6.3.0 cosmiconfig: 7.0.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) deps-regex: 0.1.4 ignore: 5.2.0 is-core-module: 2.11.0 @@ -5613,9 +5295,9 @@ packages: readdirp: 3.6.0 require-package-name: 2.0.1 resolve: 1.22.1 - sass: 1.56.0 + sass: 1.54.8 scss-parser: 1.0.5 - semver: 7.3.8 + semver: 7.3.7 yargs: 16.2.0 transitivePeerDependencies: - supports-color @@ -5640,8 +5322,8 @@ packages: dependencies: path-type: 4.0.0 - /dirfilename@1.1.1: - resolution: {integrity: sha512-ovfE0+nTK5JhKW4XXcR+M1CjHFtL6Mor4yzlpb1sJcSA2KlMIZLWSKP5NHz+2GF9oqoJlQEZEhJa2KsocfpvDQ==} + /dirfilename@1.0.4: + resolution: {integrity: sha512-JajCQGaYRLLtTTl5tKV5nRICb+DsxSu1Mp5UA+OiPNli1WDabI2oS/UBt96yhn9L3zFLM4VlQ7LDemTd2Kfipg==} engines: {node: '>=16.0.0'} /doctrine@2.1.0: @@ -5663,7 +5345,7 @@ packages: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: '@babel/runtime': 7.21.0 - csstype: 3.1.1 + csstype: 3.1.0 dev: true /dom-serializer@1.4.1: @@ -5724,8 +5406,8 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - /electron-to-chromium@1.4.284: - resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} + /electron-to-chromium@1.4.251: + resolution: {integrity: sha512-k4o4cFrWPv4SoJGGAydd07GmlRVzmeDIJ6MaEChTUjk4Dmomn189tCicSzil2oyvbPoGgg2suwPDNWq4gWRhoQ==} /emoji-regex@10.2.1: resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==} @@ -5764,52 +5446,85 @@ packages: dependencies: is-arrayish: 0.2.1 - /es-abstract@1.20.4: - resolution: {integrity: sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==} + /es-abstract@1.20.2: + resolution: {integrity: sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 es-to-primitive: 1.2.1 function-bind: 1.1.1 function.prototype.name: 1.1.5 + get-intrinsic: 1.1.3 + get-symbol-description: 1.0.0 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-symbols: 1.0.3 + internal-slot: 1.0.3 + is-callable: 1.2.6 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-weakref: 1.0.2 + object-inspect: 1.12.2 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + string.prototype.trimend: 1.0.5 + string.prototype.trimstart: 1.0.5 + unbox-primitive: 1.0.2 + + /es-abstract@1.21.2: + resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.5 get-intrinsic: 1.2.0 get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 has: 1.0.3 has-property-descriptors: 1.0.0 + has-proto: 1.0.1 has-symbols: 1.0.3 internal-slot: 1.0.5 + is-array-buffer: 3.0.2 is-callable: 1.2.7 is-negative-zero: 2.0.2 is-regex: 1.1.4 is-shared-array-buffer: 1.0.2 is-string: 1.0.7 + is-typed-array: 1.1.10 is-weakref: 1.0.2 object-inspect: 1.12.3 object-keys: 1.1.1 object.assign: 4.1.4 regexp.prototype.flags: 1.4.3 safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 string.prototype.trimend: 1.0.6 string.prototype.trimstart: 1.0.6 + typed-array-length: 1.0.4 unbox-primitive: 1.0.2 - - /es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.0 - has-symbols: 1.0.3 - is-arguments: 1.1.1 - is-map: 2.0.2 - is-set: 2.0.2 - is-string: 1.0.7 - isarray: 2.0.5 - stop-iteration-iterator: 1.0.0 + which-typed-array: 1.1.9 /es-module-lexer@0.10.5: resolution: {integrity: sha512-+7IwY/kiGAacQfY+YBhKMvEmyAJnw5grTUgjG85Pe7vcUI/6b7pZjZG8nQ7+48YhzEAEqrEgD2dCz/JIK+AYvw==} dev: true + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.0 + has: 1.0.3 + has-tostringtag: 1.0.0 + /es-shim-unscopables@1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} dependencies: @@ -5819,21 +5534,23 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: - is-callable: 1.2.7 + is-callable: 1.2.6 is-date-object: 1.0.5 is-symbol: 1.0.4 - /esbuild-android-64@0.15.13: - resolution: {integrity: sha512-yRorukXBlokwTip+Sy4MYskLhJsO0Kn0/Fj43s1krVblfwP+hMD37a4Wmg139GEsMLl+vh8WXp2mq/cTA9J97g==} + /esbuild-android-64@0.15.8: + resolution: {integrity: sha512-bVh8FIKOolF7/d4AMzt7xHlL0Ljr+mYKSHI39TJWDkybVWHdn6+4ODL3xZGHOxPpdRpitemXA1WwMKYBsw8dGw==} engines: {node: '>=12'} cpu: [x64] os: [android] requiresBuild: true + dependencies: + esbuild-wasm: 0.15.8 dev: true optional: true - /esbuild-android-arm64@0.15.13: - resolution: {integrity: sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==} + /esbuild-android-arm64@0.15.8: + resolution: {integrity: sha512-ReAMDAHuo0H1h9LxRabI6gwYPn8k6WiUeyxuMvx17yTrJO+SCnIfNc/TSPFvDwtK9MiyiKG/2dBYHouT/M0BXQ==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -5841,8 +5558,8 @@ packages: dev: true optional: true - /esbuild-darwin-64@0.15.13: - resolution: {integrity: sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==} + /esbuild-darwin-64@0.15.8: + resolution: {integrity: sha512-KaKcGfJ+yto7Fo5gAj3xwxHMd1fBIKatpCHK8znTJLVv+9+NN2/tIPBqA4w5rBwjX0UqXDeIE2v1xJP+nGEXgA==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -5850,8 +5567,8 @@ packages: dev: true optional: true - /esbuild-darwin-arm64@0.15.13: - resolution: {integrity: sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==} + /esbuild-darwin-arm64@0.15.8: + resolution: {integrity: sha512-8tjEaBgAKnXCkP7bhEJmEqdG9HEV6oLkF36BrMzpfW2rgaw0c48Zrxe+9RlfeGvs6gDF4w+agXyTjikzsS3izw==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -5859,8 +5576,8 @@ packages: dev: true optional: true - /esbuild-freebsd-64@0.15.13: - resolution: {integrity: sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==} + /esbuild-freebsd-64@0.15.8: + resolution: {integrity: sha512-jaxcsGHYzn2L0/lffON2WfH4Nc+d/EwozVTP5K2v016zxMb5UQMhLoJzvLgBqHT1SG0B/mO+a+THnJCMVg15zw==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -5868,8 +5585,8 @@ packages: dev: true optional: true - /esbuild-freebsd-arm64@0.15.13: - resolution: {integrity: sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==} + /esbuild-freebsd-arm64@0.15.8: + resolution: {integrity: sha512-2xp2UlljMvX8HExtcg7VHaeQk8OBU0CSl1j18B5CcZmSDkLF9p3utuMXIopG3a08fr9Hv+Dz6+seSXUow/G51w==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -5877,8 +5594,8 @@ packages: dev: true optional: true - /esbuild-linux-32@0.15.13: - resolution: {integrity: sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==} + /esbuild-linux-32@0.15.8: + resolution: {integrity: sha512-9u1E54BRz1FQMl86iaHK146+4ID2KYNxL3trLZT4QLLx3M7Q9n4lGG3lrzqUatGR2cKy8c33b0iaCzsItZWkFg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -5886,8 +5603,8 @@ packages: dev: true optional: true - /esbuild-linux-64@0.15.13: - resolution: {integrity: sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==} + /esbuild-linux-64@0.15.8: + resolution: {integrity: sha512-4HxrsN9eUzJXdVGMTYA5Xler82FuZUu21bXKN42zcLHHNKCAMPUzD62I+GwDhsdgUBAUj0tRXDdsQHgaP6v0HA==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -5895,8 +5612,8 @@ packages: dev: true optional: true - /esbuild-linux-arm64@0.15.13: - resolution: {integrity: sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==} + /esbuild-linux-arm64@0.15.8: + resolution: {integrity: sha512-1OCm7Aq0tEJT70PbxmHSGYDLYP8DKH8r4Nk7/XbVzWaduo9beCjGBB+tGZIHK6DdTQ3h00/4Tb/70YMH/bOtKg==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -5904,8 +5621,8 @@ packages: dev: true optional: true - /esbuild-linux-arm@0.15.13: - resolution: {integrity: sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==} + /esbuild-linux-arm@0.15.8: + resolution: {integrity: sha512-7DVBU9SFjX4+vBwt8tHsUCbE6Vvl6y6FQWHAgyw1lybC5gULqn/WnjHYHN2/LJaZRsDBvxWT4msEgwLGq1Wd3Q==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -5913,8 +5630,8 @@ packages: dev: true optional: true - /esbuild-linux-mips64le@0.15.13: - resolution: {integrity: sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==} + /esbuild-linux-mips64le@0.15.8: + resolution: {integrity: sha512-yeFoNPVFPEzZvFYBfUQNG2TjGRaCyV1E27OcOg4LOtnGrxb2wA+mkW3luckyv1CEyd00mpAg7UdHx8nlx3ghgA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -5922,8 +5639,8 @@ packages: dev: true optional: true - /esbuild-linux-ppc64le@0.15.13: - resolution: {integrity: sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==} + /esbuild-linux-ppc64le@0.15.8: + resolution: {integrity: sha512-CEyMMUUNabXibw8OSNmBXhOIGhnjNVl5Lpseiuf00iKN0V47oqDrbo4dsHz1wH62m49AR8iG8wpDlTqfYgKbtg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -5931,8 +5648,8 @@ packages: dev: true optional: true - /esbuild-linux-riscv64@0.15.13: - resolution: {integrity: sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==} + /esbuild-linux-riscv64@0.15.8: + resolution: {integrity: sha512-OCGSOaspMUjexSCU8ZiA0UnV/NiRU+s2vIfEcAQWQ6u32R+2luyfh/4ZaY6jFbylJE07Esc/yRvb9Q5fXuClXA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -5940,8 +5657,8 @@ packages: dev: true optional: true - /esbuild-linux-s390x@0.15.13: - resolution: {integrity: sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==} + /esbuild-linux-s390x@0.15.8: + resolution: {integrity: sha512-RHdpdfxRTSrZXZJlFSLazFU4YwXLB5Rgf6Zr5rffqSsO4y9JybgtKO38bFwxZNlDXliYISXN/YROKrG9s7mZQA==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -5949,8 +5666,8 @@ packages: dev: true optional: true - /esbuild-netbsd-64@0.15.13: - resolution: {integrity: sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==} + /esbuild-netbsd-64@0.15.8: + resolution: {integrity: sha512-VolFFRatBH09T5QMWhiohAWCOien1R1Uz9K0BRVVTBgBaVBt7eArsXTKxVhUgRf2vwu2c2SXkuP0r7HLG0eozw==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -5958,8 +5675,8 @@ packages: dev: true optional: true - /esbuild-openbsd-64@0.15.13: - resolution: {integrity: sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==} + /esbuild-openbsd-64@0.15.8: + resolution: {integrity: sha512-HTAPlg+n4kUeE/isQxlCfsOz0xJGNoT5LJ9oYZWFKABfVf4Ycu7Zlf5ITgOnrdheTkz8JeL/gISIOCFAoOXrSA==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -5967,8 +5684,8 @@ packages: dev: true optional: true - /esbuild-sunos-64@0.15.13: - resolution: {integrity: sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==} + /esbuild-sunos-64@0.15.8: + resolution: {integrity: sha512-qMP/jR/FzcIOwKj+W+Lb+8Cfr8GZHbHUJxAPi7DUhNZMQ/6y7sOgRzlOSpRrbbUntrRZh0MqOyDhJ3Gpo6L1QA==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -5976,8 +5693,16 @@ packages: dev: true optional: true - /esbuild-windows-32@0.15.13: - resolution: {integrity: sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==} + /esbuild-wasm@0.15.8: + resolution: {integrity: sha512-Y7uCl5RNO4URjlemjdx++ukVHEMt5s5AfMWYUnMiK4Sry+pPCvQIctzXq6r6FKCyGKjX6/NGMCqR2OX6aLxj0w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-32@0.15.8: + resolution: {integrity: sha512-RKR1QHh4iWzjUhkP8Yqi75PPz/KS+b8zw3wUrzw6oAkj+iU5Qtyj61ZDaSG3Qf2vc6hTIUiPqVTqBH0NpXFNwg==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -5985,8 +5710,8 @@ packages: dev: true optional: true - /esbuild-windows-64@0.15.13: - resolution: {integrity: sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==} + /esbuild-windows-64@0.15.8: + resolution: {integrity: sha512-ag9ptYrsizgsR+PQE8QKeMqnosLvAMonQREpLw4evA4FFgOBMLEat/dY/9txbpozTw9eEOYyD3a4cE9yTu20FA==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -5994,8 +5719,8 @@ packages: dev: true optional: true - /esbuild-windows-arm64@0.15.13: - resolution: {integrity: sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==} + /esbuild-windows-arm64@0.15.8: + resolution: {integrity: sha512-dbpAb0VyPaUs9mgw65KRfQ9rqiWCHpNzrJusoPu+LpEoswosjt/tFxN7cd2l68AT4qWdBkzAjDLRon7uqMeWcg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -6003,64 +5728,64 @@ packages: dev: true optional: true - /esbuild@0.15.13: - resolution: {integrity: sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==} + /esbuild@0.15.8: + resolution: {integrity: sha512-Remsk2dmr1Ia65sU+QasE6svJbsHe62lzR+CnjpUvbZ+uSYo1SitiOWPRfZQkCu82YWZBBKXiD/j0i//XWMZ+Q==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.15.13 - '@esbuild/linux-loong64': 0.15.13 - esbuild-android-64: 0.15.13 - esbuild-android-arm64: 0.15.13 - esbuild-darwin-64: 0.15.13 - esbuild-darwin-arm64: 0.15.13 - esbuild-freebsd-64: 0.15.13 - esbuild-freebsd-arm64: 0.15.13 - esbuild-linux-32: 0.15.13 - esbuild-linux-64: 0.15.13 - esbuild-linux-arm: 0.15.13 - esbuild-linux-arm64: 0.15.13 - esbuild-linux-mips64le: 0.15.13 - esbuild-linux-ppc64le: 0.15.13 - esbuild-linux-riscv64: 0.15.13 - esbuild-linux-s390x: 0.15.13 - esbuild-netbsd-64: 0.15.13 - esbuild-openbsd-64: 0.15.13 - esbuild-sunos-64: 0.15.13 - esbuild-windows-32: 0.15.13 - esbuild-windows-64: 0.15.13 - esbuild-windows-arm64: 0.15.13 - dev: true - - /esbuild@0.17.12: - resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==} + '@esbuild/android-arm': 0.15.8 + '@esbuild/linux-loong64': 0.15.8 + esbuild-android-64: 0.15.8 + esbuild-android-arm64: 0.15.8 + esbuild-darwin-64: 0.15.8 + esbuild-darwin-arm64: 0.15.8 + esbuild-freebsd-64: 0.15.8 + esbuild-freebsd-arm64: 0.15.8 + esbuild-linux-32: 0.15.8 + esbuild-linux-64: 0.15.8 + esbuild-linux-arm: 0.15.8 + esbuild-linux-arm64: 0.15.8 + esbuild-linux-mips64le: 0.15.8 + esbuild-linux-ppc64le: 0.15.8 + esbuild-linux-riscv64: 0.15.8 + esbuild-linux-s390x: 0.15.8 + esbuild-netbsd-64: 0.15.8 + esbuild-openbsd-64: 0.15.8 + esbuild-sunos-64: 0.15.8 + esbuild-windows-32: 0.15.8 + esbuild-windows-64: 0.15.8 + esbuild-windows-arm64: 0.15.8 + dev: true + + /esbuild@0.17.15: + resolution: {integrity: sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.17.12 - '@esbuild/android-arm64': 0.17.12 - '@esbuild/android-x64': 0.17.12 - '@esbuild/darwin-arm64': 0.17.12 - '@esbuild/darwin-x64': 0.17.12 - '@esbuild/freebsd-arm64': 0.17.12 - '@esbuild/freebsd-x64': 0.17.12 - '@esbuild/linux-arm': 0.17.12 - '@esbuild/linux-arm64': 0.17.12 - '@esbuild/linux-ia32': 0.17.12 - '@esbuild/linux-loong64': 0.17.12 - '@esbuild/linux-mips64el': 0.17.12 - '@esbuild/linux-ppc64': 0.17.12 - '@esbuild/linux-riscv64': 0.17.12 - '@esbuild/linux-s390x': 0.17.12 - '@esbuild/linux-x64': 0.17.12 - '@esbuild/netbsd-x64': 0.17.12 - '@esbuild/openbsd-x64': 0.17.12 - '@esbuild/sunos-x64': 0.17.12 - '@esbuild/win32-arm64': 0.17.12 - '@esbuild/win32-ia32': 0.17.12 - '@esbuild/win32-x64': 0.17.12 + '@esbuild/android-arm': 0.17.15 + '@esbuild/android-arm64': 0.17.15 + '@esbuild/android-x64': 0.17.15 + '@esbuild/darwin-arm64': 0.17.15 + '@esbuild/darwin-x64': 0.17.15 + '@esbuild/freebsd-arm64': 0.17.15 + '@esbuild/freebsd-x64': 0.17.15 + '@esbuild/linux-arm': 0.17.15 + '@esbuild/linux-arm64': 0.17.15 + '@esbuild/linux-ia32': 0.17.15 + '@esbuild/linux-loong64': 0.17.15 + '@esbuild/linux-mips64el': 0.17.15 + '@esbuild/linux-ppc64': 0.17.15 + '@esbuild/linux-riscv64': 0.17.15 + '@esbuild/linux-s390x': 0.17.15 + '@esbuild/linux-x64': 0.17.15 + '@esbuild/netbsd-x64': 0.17.15 + '@esbuild/openbsd-x64': 0.17.15 + '@esbuild/sunos-x64': 0.17.15 + '@esbuild/win32-arm64': 0.17.15 + '@esbuild/win32-ia32': 0.17.15 + '@esbuild/win32-x64': 0.17.15 /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -6097,11 +5822,11 @@ packages: eslint: 8.36.0 eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) object.assign: 4.1.4 - object.entries: 1.1.6 + object.entries: 1.1.5 semver: 6.3.0 dev: true - /eslint-config-airbnb@19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.36.0): + /eslint-config-airbnb@19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.6.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.31.8)(eslint@8.36.0): resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -6114,11 +5839,11 @@ packages: eslint: 8.36.0 eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.36.0) eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) - eslint-plugin-jsx-a11y: 6.7.1(eslint@8.36.0) - eslint-plugin-react: 7.32.2(eslint@8.36.0) + eslint-plugin-jsx-a11y: 6.6.1(eslint@8.36.0) + eslint-plugin-react: 7.31.8(eslint@8.36.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.36.0) object.assign: 4.1.4 - object.entries: 1.1.6 + object.entries: 1.1.5 dev: true /eslint-config-prettier@8.8.0(eslint@8.36.0): @@ -6145,13 +5870,13 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) enhanced-resolve: 5.10.0 eslint: 8.36.0 eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) get-tsconfig: 4.2.0 globby: 13.1.2 - is-core-module: 2.11.0 + is-core-module: 2.10.0 is-glob: 4.0.3 synckit: 0.8.4 transitivePeerDependencies: @@ -6186,35 +5911,6 @@ packages: transitivePeerDependencies: - supports-color - /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint@8.36.0): - resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - debug: 3.2.7 - eslint: 8.36.0 - eslint-import-resolver-node: 0.3.7 - transitivePeerDependencies: - - supports-color - dev: false - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} @@ -6247,39 +5943,6 @@ packages: - eslint-import-resolver-webpack - supports-color - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint@8.36.0): - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.56.0(eslint@8.36.0)(typescript@5.0.2) - array-includes: 3.1.6 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.1 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.36.0 - eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint@8.36.0) - has: 1.0.3 - is-core-module: 2.11.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.6 - resolve: 1.22.1 - semver: 6.3.0 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: false - /eslint-plugin-json@3.1.0: resolution: {integrity: sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==} engines: {node: '>=12.0'} @@ -6294,24 +5957,23 @@ packages: peerDependencies: eslint: '>=6.0.0' dependencies: - '@eslint-community/eslint-utils': 4.3.0(eslint@8.36.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.36.0) eslint: 8.36.0 - jsonc-eslint-parser: 2.1.0 + jsonc-eslint-parser: 2.2.0 natural-compare: 1.4.0 - /eslint-plugin-jsx-a11y@6.7.1(eslint@8.36.0): - resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} + /eslint-plugin-jsx-a11y@6.6.1(eslint@8.36.0): + resolution: {integrity: sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==} engines: {node: '>=4.0'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 dependencies: '@babel/runtime': 7.21.0 - aria-query: 5.1.3 + aria-query: 4.2.2 array-includes: 3.1.6 - array.prototype.flatmap: 1.3.1 ast-types-flow: 0.0.7 - axe-core: 4.6.3 - axobject-query: 3.1.1 + axe-core: 4.4.3 + axobject-query: 2.2.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 eslint: 8.36.0 @@ -6319,8 +5981,6 @@ packages: jsx-ast-utils: 3.3.3 language-tags: 1.0.5 minimatch: 3.1.2 - object.entries: 1.1.6 - object.fromentries: 2.0.6 semver: 6.3.0 dev: true @@ -6349,28 +6009,27 @@ packages: eslint: 8.36.0 dev: true - /eslint-plugin-react@7.32.2(eslint@8.36.0): - resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==} + /eslint-plugin-react@7.31.8(eslint@8.36.0): + resolution: {integrity: sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 dependencies: array-includes: 3.1.6 array.prototype.flatmap: 1.3.1 - array.prototype.tosorted: 1.1.1 doctrine: 2.1.0 eslint: 8.36.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.3 minimatch: 3.1.2 - object.entries: 1.1.6 - object.fromentries: 2.0.6 - object.hasown: 1.1.2 + object.entries: 1.1.5 + object.fromentries: 2.0.5 + object.hasown: 1.1.1 object.values: 1.1.6 prop-types: 15.8.1 resolve: 2.0.0-next.4 semver: 6.3.0 - string.prototype.matchall: 4.0.8 + string.prototype.matchall: 4.0.7 dev: true /eslint-plugin-simple-import-sort@10.0.0(eslint@8.36.0): @@ -6394,20 +6053,6 @@ packages: eslint: 8.36.0 eslint-rule-composer: 0.3.0 - /eslint-plugin-unused-imports@2.0.0(eslint@8.36.0): - resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - dependencies: - eslint: 8.36.0 - eslint-rule-composer: 0.3.0 - dev: false - /eslint-rule-composer@0.3.0: resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} engines: {node: '>=4.0.0'} @@ -6435,14 +6080,18 @@ packages: resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint-visitor-keys@3.4.0: + resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint@8.36.0: resolution: {integrity: sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.3.0(eslint@8.36.0) - '@eslint-community/regexpp': 4.4.0 - '@eslint/eslintrc': 2.0.1 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.36.0) + '@eslint-community/regexpp': 4.5.0 + '@eslint/eslintrc': 2.0.2 '@eslint/js': 8.36.0 '@humanwhocodes/config-array': 0.11.8 '@humanwhocodes/module-importer': 1.0.1 @@ -6450,26 +6099,26 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 eslint-visitor-keys: 3.3.0 - espree: 9.5.0 + espree: 9.5.1 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.19.0 + globals: 13.20.0 grapheme-splitter: 1.0.4 ignore: 5.2.0 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-sdsl: 4.1.5 + js-sdsl: 4.1.4 js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 @@ -6487,25 +6136,16 @@ packages: resolution: {integrity: sha512-6slSBEV1lMKcX13DBifvnDFpNno5WXhw4j/ff7RI0y51BZiDqEe5dNhhjhIQ3iCOQuzsm2MbVzmwqbN78BBhPg==} hasBin: true dependencies: - tsx: 3.11.0 + tsx: 3.9.0 dev: true - /espree@9.4.1: - resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.8.2 - acorn-jsx: 5.3.2(acorn@8.8.2) - eslint-visitor-keys: 3.3.0 - dev: false - - /espree@9.5.0: - resolution: {integrity: sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==} + /espree@9.5.1: + resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: acorn: 8.8.2 acorn-jsx: 5.3.2(acorn@8.8.2) - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.0 /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} @@ -6631,8 +6271,8 @@ packages: /flatted@3.2.7: resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - /follow-redirects@1.15.2: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + /follow-redirects@1.15.1: + resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -6698,8 +6338,8 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.20.2 functions-have-names: 1.2.3 /functions-have-names@1.2.3: @@ -6714,7 +6354,6 @@ packages: /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - dev: true /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} @@ -6723,6 +6362,13 @@ packages: /get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + /get-intrinsic@1.1.3: + resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + /get-intrinsic@1.2.0: resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} dependencies: @@ -6742,7 +6388,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.2.0 + get-intrinsic: 1.1.3 /get-tsconfig@4.2.0: resolution: {integrity: sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==} @@ -6769,14 +6415,14 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 - /glob@8.0.3: - resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==} + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 5.1.0 + minimatch: 5.1.6 once: 1.4.0 dev: false @@ -6784,12 +6430,18 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - /globals@13.19.0: - resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} + /globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.1.4 + /globalyzer@0.1.0: resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} @@ -6840,7 +6492,6 @@ packages: whatwg-mimetype: 3.0.0 transitivePeerDependencies: - encoding - dev: true /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} @@ -6861,7 +6512,11 @@ packages: /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: - get-intrinsic: 1.2.0 + get-intrinsic: 1.1.3 + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} @@ -6882,7 +6537,6 @@ packages: /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - dev: true /helpertypes@0.0.18: resolution: {integrity: sha512-XRhfbSEmR+poXUC5/8AbmYNJb2riOT6qPzjGJZr0S9YedHiaY+/tzPYzWMUclYMEdCYo/1l8PDYrQFCj02v97w==} @@ -6924,7 +6578,7 @@ packages: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -6933,7 +6587,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -7022,6 +6676,14 @@ packages: resolution: {integrity: sha512-GOucsp9EcdlLdhPUyOTvQDnbFJtp2WBWZV1Jqe+mVnkJQBL3w96+fB84C+JL+EKXOspMdB0eMDQPDp5w9fkfZA==} dev: false + /internal-slot@1.0.3: + resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.1.3 + has: 1.0.3 + side-channel: 1.0.4 + /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} @@ -7040,13 +6702,6 @@ packages: loose-envify: 1.4.0 dev: false - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -7083,6 +6738,10 @@ packages: builtin-modules: 3.3.0 dev: false + /is-callable@1.2.6: + resolution: {integrity: sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==} + engines: {node: '>= 0.4'} + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -7091,9 +6750,14 @@ packages: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true dependencies: - ci-info: 3.5.0 + ci-info: 3.4.0 dev: true + /is-core-module@2.10.0: + resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} + dependencies: + has: 1.0.3 + /is-core-module@2.11.0: resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} dependencies: @@ -7128,9 +6792,6 @@ packages: dependencies: is-extglob: 2.1.1 - /is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - /is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: false @@ -7174,9 +6835,6 @@ packages: call-bind: 1.0.2 has-tostringtag: 1.0.0 - /is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: @@ -7211,20 +6869,11 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 - /is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 - /is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.0 - /is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -7236,9 +6885,6 @@ packages: dependencies: is-docker: 2.2.1 - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - /isbot@3.4.5: resolution: {integrity: sha512-+KD6q1BBtw0iK9aGBGSfxJ31/ZgizKRjhm8ebgJUBMx0aeeQuIJ1I72beCoIrltIZGrSm4vmrxRxrG5n1aUTtw==} engines: {node: '>=12'} @@ -7247,8 +6893,8 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - /js-sdsl@4.1.5: - resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} + /js-sdsl@4.1.4: + resolution: {integrity: sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==} /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -7276,12 +6922,12 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.8.1 + acorn: 8.8.2 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 data-urls: 3.0.2 - decimal.js: 10.4.2 + decimal.js: 10.4.3 domexception: 4.0.0 escodegen: 2.0.0 form-data: 4.0.0 @@ -7290,7 +6936,7 @@ packages: https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 nwsapi: 2.2.2 - parse5: 7.1.1 + parse5: 7.1.2 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 4.1.2 @@ -7299,7 +6945,7 @@ packages: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.11.0 + ws: 8.13.0 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -7349,7 +6995,6 @@ packages: /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true - dev: true /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} @@ -7375,19 +7020,12 @@ packages: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: - minimist: 1.2.7 + minimist: 1.2.6 /json5@2.2.1: resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} engines: {node: '>=6'} hasBin: true - dev: false - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true /jsonc-eslint-parser@2.1.0: resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==} @@ -7395,8 +7033,18 @@ packages: dependencies: acorn: 8.8.2 eslint-visitor-keys: 3.3.0 - espree: 9.5.0 - semver: 7.3.8 + espree: 9.5.1 + semver: 7.3.7 + dev: false + + /jsonc-eslint-parser@2.2.0: + resolution: {integrity: sha512-x5QjzBOORd+T2EjErIxJnkOEbLVEdD1ILEeBbIJt8Eq/zUn7P7M8qdnWiNVBK5f8oxnJpc6SBHOeeIEl/swPjg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.2 + eslint-visitor-keys: 3.3.0 + espree: 9.5.1 + semver: 7.3.7 /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} @@ -7511,7 +7159,6 @@ packages: /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -7537,6 +7184,11 @@ packages: dependencies: js-tokens: 4.0.0 + /loupe@2.3.4: + resolution: {integrity: sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==} + dependencies: + get-func-name: 2.0.0 + /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} dependencies: @@ -7553,7 +7205,6 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 - dev: true /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} @@ -7564,7 +7215,6 @@ packages: /lz-string@1.4.4: resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} hasBin: true - dev: false /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} @@ -7577,8 +7227,8 @@ packages: sourcemap-codec: 1.4.8 dev: false - /magic-string@0.26.7: - resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} + /magic-string@0.26.3: + resolution: {integrity: sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg==} engines: {node: '>=12'} dependencies: sourcemap-codec: 1.4.8 @@ -7610,7 +7260,7 @@ packages: dependencies: '@types/minimist': 1.2.2 camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 + decamelize-keys: 1.1.0 hard-rejection: 2.1.0 minimist-options: 4.1.0 normalize-package-data: 2.5.0 @@ -7652,8 +7302,8 @@ packages: dependencies: brace-expansion: 1.1.11 - /minimatch@5.1.0: - resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==} + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 @@ -7668,8 +7318,8 @@ packages: kind-of: 6.0.3 dev: true - /minimist@1.2.7: - resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + /minimist@1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} /mixme@0.5.4: resolution: {integrity: sha512-3KYa4m4Vlqx98GPdOHghxSdNtTvcP8E0kkaJ5Dlh+h2DRzF7zpuVVcA8B0QpKd11YJeP9QQ7ASkKzOeu195Wzw==} @@ -7687,7 +7337,6 @@ packages: /mrmime@1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} engines: {node: '>=10'} - dev: true /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -7735,7 +7384,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-pty@0.10.1: resolution: {integrity: sha512-JTdtUS0Im/yRsWJSx7yiW9rtpfmxqxolrtnyKwPLI+6XqTAPW/O2MjS8FYL4I5TsMbH2lVgDb2VMjp+9LoQGNg==} @@ -7778,16 +7426,12 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + /object-inspect@1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - /object-is@1.1.5: - resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -7802,33 +7446,33 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 + define-properties: 1.1.4 has-symbols: 1.0.3 object-keys: 1.1.1 - /object.entries@1.1.6: - resolution: {integrity: sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==} + /object.entries@1.1.5: + resolution: {integrity: sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.20.2 dev: true - /object.fromentries@2.0.6: - resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} + /object.fromentries@2.0.5: + resolution: {integrity: sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 dev: true - /object.hasown@1.1.2: - resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} + /object.hasown@1.1.1: + resolution: {integrity: sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==} dependencies: - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 dev: true /object.values@1.1.6: @@ -7836,8 +7480,8 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -7962,7 +7606,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.21.4 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -7974,11 +7618,6 @@ packages: parse5: 7.1.2 dev: true - /parse5@7.1.1: - resolution: {integrity: sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==} - dependencies: - entities: 4.4.0 - /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: @@ -8069,8 +7708,8 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-convert-values@5.1.3(postcss@8.4.20): - resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} + /postcss-convert-values@5.1.2(postcss@8.4.20): + resolution: {integrity: sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -8133,19 +7772,19 @@ packages: yaml: 1.10.2 dev: false - /postcss-merge-longhand@5.1.7(postcss@8.4.20): - resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} + /postcss-merge-longhand@5.1.6(postcss@8.4.20): + resolution: {integrity: sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 dependencies: postcss: 8.4.20 postcss-value-parser: 4.2.0 - stylehacks: 5.1.1(postcss@8.4.20) + stylehacks: 5.1.0(postcss@8.4.20) dev: false - /postcss-merge-rules@5.1.3(postcss@8.4.20): - resolution: {integrity: sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==} + /postcss-merge-rules@5.1.2(postcss@8.4.20): + resolution: {integrity: sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -8179,8 +7818,8 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-minify-params@5.1.4(postcss@8.4.20): - resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} + /postcss-minify-params@5.1.3(postcss@8.4.20): + resolution: {integrity: sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -8317,8 +7956,8 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-normalize-unicode@5.1.1(postcss@8.4.20): - resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} + /postcss-normalize-unicode@5.1.0(postcss@8.4.20): + resolution: {integrity: sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -8360,8 +7999,8 @@ packages: postcss-value-parser: 4.2.0 dev: false - /postcss-reduce-initial@5.1.1(postcss@8.4.20): - resolution: {integrity: sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==} + /postcss-reduce-initial@5.1.0(postcss@8.4.20): + resolution: {integrity: sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -8466,12 +8105,6 @@ packages: dependencies: fast-diff: 1.2.0 - /prettier@2.8.1: - resolution: {integrity: sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: false - /prettier@2.8.6: resolution: {integrity: sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==} engines: {node: '>=10.13.0'} @@ -8579,6 +8212,10 @@ packages: /react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + /react-portal@4.2.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-vS18idTmevQxyQpnde0Td6ZcUlv+pD8GTyR42n3CHUQq9OHi1C4jDE4ZWEbEsrbrLRhSECYiao58cvocwMtP7Q==} peerDependencies: @@ -8595,8 +8232,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /react-transition-group@4.4.5(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + /react-transition-group@4.4.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==} peerDependencies: react: '*' react-dom: '*' @@ -8670,11 +8307,9 @@ packages: engines: {node: '>=4'} dependencies: regenerate: 1.4.2 - dev: true /regenerate@1.4.2: resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true /regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} @@ -8683,14 +8318,13 @@ packages: resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} dependencies: '@babel/runtime': 7.21.0 - dev: true /regexp.prototype.flags@1.4.3: resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 + define-properties: 1.1.4 functions-have-names: 1.2.3 /regexpu-core@5.2.1: @@ -8703,18 +8337,15 @@ packages: regjsparser: 0.9.1 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.0.0 - dev: true /regjsgen@0.7.1: resolution: {integrity: sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==} - dev: true /regjsparser@0.9.1: resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} hasBin: true dependencies: jsesc: 0.5.0 - dev: true /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -8771,7 +8402,7 @@ packages: peerDependencies: rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 dependencies: - '@rollup/plugin-inject': 5.0.2(rollup@3.9.1) + '@rollup/plugin-inject': 5.0.3(rollup@3.9.1) rollup: 3.9.1 dev: false @@ -8783,7 +8414,7 @@ packages: dependencies: chalk: 4.1.2 concat-with-sourcemaps: 1.1.0 - cssnano: 5.1.14(postcss@8.4.20) + cssnano: 5.1.13(postcss@8.4.20) import-cwd: 3.0.0 p-queue: 6.6.2 pify: 5.0.0 @@ -8799,7 +8430,7 @@ packages: - ts-node dev: false - /rollup-plugin-ts@3.0.2(rollup@3.9.1)(typescript@5.0.2): + /rollup-plugin-ts@3.0.2(@babel/core@7.19.1)(@babel/plugin-transform-runtime@7.21.0)(@babel/preset-env@7.20.2)(@babel/preset-typescript@7.21.0)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.2): resolution: {integrity: sha512-67qi2QTHewhLyKDG6fX3jpohWpmUPPIT/xJ7rsYK46X6MqmoWy64Ti0y8ygPfLv8mXDCdRZUofM3mTxDfCswRA==} engines: {node: '>=14.9.0', npm: '>=7.0.0', pnpm: '>=3.2.0', yarn: '>=1.13'} peerDependencies: @@ -8828,6 +8459,11 @@ packages: '@swc/helpers': optional: true dependencies: + '@babel/core': 7.19.1 + '@babel/plugin-transform-runtime': 7.21.0(@babel/core@7.19.1) + '@babel/preset-env': 7.20.2(@babel/core@7.19.1) + '@babel/preset-typescript': 7.21.0(@babel/core@7.19.1) + '@babel/runtime': 7.21.0 '@rollup/pluginutils': 4.2.1 '@wessberg/stringutil': 1.0.19 ansi-colors: 4.1.3 @@ -8835,7 +8471,7 @@ packages: browserslist-generator: 1.0.66 compatfactory: 1.0.1(typescript@5.0.2) crosspath: 2.0.0 - magic-string: 0.26.7 + magic-string: 0.26.3 rollup: 3.9.1 ts-clone-node: 1.0.0(typescript@5.0.2) tslib: 2.5.0 @@ -8869,6 +8505,9 @@ packages: tslib: 2.5.0 dev: true + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + /safe-identifier@0.4.2: resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} dev: false @@ -8883,8 +8522,8 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - /sass@1.56.0: - resolution: {integrity: sha512-WFJ9XrpkcnqZcYuLRJh5qiV6ibQOR4AezleeEjTjMsCocYW59dEG19U3fwTTXxzi2Ed3yjPBp727hbbj53pHFw==} + /sass@1.54.8: + resolution: {integrity: sha512-ib4JhLRRgbg6QVy6bsv5uJxnJMTS2soVcCp9Y88Extyy13A8vV0G1fAwujOzmNkFQbR3LvedudAMbtuNRPbQww==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -8925,8 +8564,8 @@ packages: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - /semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + /semver@7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} engines: {node: '>=10'} hasBin: true dependencies: @@ -8988,8 +8627,8 @@ packages: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.2.0 - object-inspect: 1.12.3 + get-intrinsic: 1.1.3 + object-inspect: 1.12.2 /siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -9005,7 +8644,6 @@ packages: '@polka/url': 1.0.0-next.21 mrmime: 1.0.1 totalist: 3.0.0 - dev: true /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -9109,12 +8747,6 @@ packages: /std-env@3.3.2: resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} - /stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} - dependencies: - internal-slot: 1.0.5 - /stream-buffers@0.2.6: resolution: {integrity: sha512-ZRpmWyuCdg0TtNKk8bEqvm13oQvXMmzXDsfD4cBgcx5LouborvU5pm3JMkdTP3HcszyUI08AM1dHMXA5r2g6Sg==} engines: {node: '>= 0.3.0'} @@ -9146,12 +8778,12 @@ packages: emoji-regex: 9.2.2 strip-ansi: 7.0.1 - /string.prototype.matchall@4.0.8: - resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} + /string.prototype.matchall@4.0.7: + resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 get-intrinsic: 1.2.0 has-symbols: 1.0.3 internal-slot: 1.0.5 @@ -9159,19 +8791,41 @@ packages: side-channel: 1.0.4 dev: true + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.21.2 + + /string.prototype.trimend@1.0.5: + resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 + /string.prototype.trimend@1.0.6: resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 + + /string.prototype.trimstart@1.0.5: + resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + es-abstract: 1.20.2 /string.prototype.trimstart@1.0.6: resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} dependencies: call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.20.4 + define-properties: 1.1.4 + es-abstract: 1.21.2 /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} @@ -9200,8 +8854,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - /strip-literal@1.0.0: - resolution: {integrity: sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==} + /strip-literal@1.0.1: + resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} dependencies: acorn: 8.8.2 @@ -9209,8 +8863,8 @@ packages: resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} dev: false - /styled-components@5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0): - resolution: {integrity: sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==} + /styled-components@5.3.5(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==} engines: {node: '>=10'} requiresBuild: true peerDependencies: @@ -9219,22 +8873,22 @@ packages: react-is: '>= 16.8.0' dependencies: '@babel/helper-module-imports': 7.18.6 - '@babel/traverse': 7.20.1(supports-color@5.5.0) - '@emotion/is-prop-valid': 1.2.0 + '@babel/traverse': 7.18.9(supports-color@5.5.0) + '@emotion/is-prop-valid': 1.1.3 '@emotion/stylis': 0.8.5 '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.0.7(styled-components@5.3.6) + babel-plugin-styled-components: 2.0.7(styled-components@5.3.5) css-to-react-native: 3.0.0 hoist-non-react-statics: 3.3.2 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-is: 17.0.2 + react-is: 18.2.0 shallowequal: 1.1.0 supports-color: 5.5.0 dev: true - /stylehacks@5.1.1(postcss@8.4.20): - resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} + /stylehacks@5.1.0(postcss@8.4.20): + resolution: {integrity: sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==} engines: {node: ^10 || ^12 || >=14.0} peerDependencies: postcss: ^8.2.15 @@ -9306,8 +8960,8 @@ packages: globalyzer: 0.1.0 globrex: 0.1.2 - /tinybench@2.3.1: - resolution: {integrity: sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==} + /tinybench@2.4.0: + resolution: {integrity: sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==} /tinypool@0.4.0: resolution: {integrity: sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA==} @@ -9337,7 +8991,6 @@ packages: /totalist@3.0.0: resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} engines: {node: '>=6'} - dev: true /tough-cookie@4.1.2: resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} @@ -9350,7 +9003,6 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} @@ -9384,7 +9036,7 @@ packages: dependencies: '@types/json5': 0.0.29 json5: 1.0.1 - minimist: 1.2.7 + minimist: 1.2.6 strip-bom: 3.0.0 /tslib@1.14.1: @@ -9402,13 +9054,13 @@ packages: tslib: 1.14.1 typescript: 5.0.2 - /tsx@3.11.0: - resolution: {integrity: sha512-q+q4xxu41+AafVwvAGqtNJ1ekPFd33ZhTMXvgIpHMqv/W89efwDRE9IyjhEAZm5iTHsshKaf1BYWSk789BrNCA==} + /tsx@3.9.0: + resolution: {integrity: sha512-ofxsE+qjqCYYq4UBt5khglvb+ESgxef1YpuNcdQI92kvcAT2tZVrnSK3g4bRXTUhLmKHcC5q8vIZA47os/stng==} hasBin: true dependencies: - '@esbuild-kit/cjs-loader': 2.4.0 - '@esbuild-kit/core-utils': 3.0.0 - '@esbuild-kit/esm-loader': 2.5.0 + '@esbuild-kit/cjs-loader': 2.3.3 + '@esbuild-kit/core-utils': 2.3.0 + '@esbuild-kit/esm-loader': 2.4.2 optionalDependencies: fsevents: 2.3.2 dev: true @@ -9424,7 +9076,7 @@ packages: smartwrap: 2.0.2 strip-ansi: 6.0.1 wcwidth: 1.0.1 - yargs: 17.6.2 + yargs: 17.5.1 dev: true /type-check@0.3.2: @@ -9462,13 +9114,20 @@ packages: engines: {node: '>=8'} dev: true + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.10 + /typescript@5.0.2: resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==} engines: {node: '>=12.20'} hasBin: true - /ua-parser-js@1.0.32: - resolution: {integrity: sha512-dXVsz3M4j+5tTiovFVyVqssXBu5HM47//YSOeZ9fQkdDKkfzv2v3PP1jmH6FUyPW+yCSn7aBVK1fGGKNhowdDA==} + /ua-parser-js@1.0.2: + resolution: {integrity: sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==} dev: false /uberproto@1.2.0: @@ -9489,7 +9148,6 @@ packages: /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} - dev: true /unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} @@ -9497,17 +9155,14 @@ packages: dependencies: unicode-canonical-property-names-ecmascript: 2.0.0 unicode-property-aliases-ecmascript: 2.1.0 - dev: true /unicode-match-property-value-ecmascript@2.0.0: resolution: {integrity: sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==} engines: {node: '>=4'} - dev: true /unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} - dev: true /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} @@ -9523,8 +9178,8 @@ packages: engines: {node: '>= 10.0.0'} dev: true - /update-browserslist-db@1.0.10(browserslist@4.21.4): - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + /update-browserslist-db@1.0.9(browserslist@4.21.4): + resolution: {integrity: sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -9536,7 +9191,7 @@ packages: /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: - punycode: 2.3.0 + punycode: 2.1.1 /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -9555,33 +9210,13 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite-node@0.29.7(@types/node@18.15.5): - resolution: {integrity: sha512-PakCZLvz37yFfUPWBnLa1OYHPCGm5v4pmRrTcFN4V/N/T3I6tyP3z07S//9w+DdeL7vVd0VSeyMZuAh+449ZWw==} - engines: {node: '>=v14.16.0'} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4 - mlly: 1.2.0 - pathe: 1.1.0 - picocolors: 1.0.0 - vite: 4.2.1(@types/node@18.15.5) - transitivePeerDependencies: - - '@types/node' - - less - - sass - - stylus - - sugarss - - supports-color - - terser - /vite-node@0.29.8(@types/node@18.15.5): resolution: {integrity: sha512-b6OtCXfk65L6SElVM20q5G546yu10/kNrhg08afEoWlFRJXFq9/6glsvSVY+aI6YeC1tu2TtAqI2jHEQmOmsFw==} engines: {node: '>=v14.16.0'} hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 @@ -9594,56 +9229,24 @@ packages: - sugarss - supports-color - terser - dev: true /vite-plugin-fonts@0.7.0(vite@4.2.1): resolution: {integrity: sha512-fisKirkQrA2RFwcyI96SENLu1FyRYNIiC/l5DGdD8oV3OsAWGrYKs0e7/VZF6l0rm0QiYA2sOVTzYfrLAzP9cw==} + deprecated: renamed to `unplugin-fonts`, see https://github.com/cssninjaStudio/unplugin-fonts/releases/tag/v1.0.0 peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 dependencies: fast-glob: 3.2.12 - vite: 4.2.1 + vite: 4.2.1(@types/node@18.15.5) - /vite-plugin-mpa@1.1.4: - resolution: {integrity: sha512-sLXMOdMl8t9B9/sxXXZ9CLt8QudhGSSKCX+bZ/ePaO7kp4SdoA5d6CV+EnCyNuQCenAbXKJzk3nM8Do0RgmSpA==} + /vite-plugin-mpa@1.1.3: + resolution: {integrity: sha512-qv2/mNoezHeWgdXThoU7JqAwaIQOPFJn97fucl9//eUjiYxGwx7A1KFnBX4qs735PgaozXshltQa+VO0nt3fwg==} dependencies: connect-history-api-fallback: 1.6.0 shelljs: 0.8.5 yargs: 16.2.0 dev: true - /vite@4.2.1: - resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - esbuild: 0.17.12 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.9.1 - optionalDependencies: - fsevents: 2.3.2 - /vite@4.2.1(@types/node@18.15.5): resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -9670,15 +9273,15 @@ packages: optional: true dependencies: '@types/node': 18.15.5 - esbuild: 0.17.12 + esbuild: 0.17.15 postcss: 8.4.21 resolve: 1.22.1 rollup: 3.9.1 optionalDependencies: fsevents: 2.3.2 - /vitest@0.29.7(@vitest/ui@0.29.7): - resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} + /vitest@0.29.8(@vitest/ui@0.23.4)(happy-dom@8.9.0)(jsdom@21.1.1): + resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==} engines: {node: '>=v14.16.0'} hasBin: true peerDependencies: @@ -9687,6 +9290,7 @@ packages: '@vitest/ui': '*' happy-dom: '*' jsdom: '*' + playwright: '*' safaridriver: '*' webdriverio: '*' peerDependenciesMeta: @@ -9700,67 +9304,7 @@ packages: optional: true jsdom: optional: true - safaridriver: - optional: true - webdriverio: - optional: true - dependencies: - '@types/chai': 4.3.4 - '@types/chai-subset': 1.3.3 - '@types/node': 18.15.5 - '@vitest/expect': 0.29.7 - '@vitest/runner': 0.29.7 - '@vitest/spy': 0.29.7 - '@vitest/ui': 0.29.7 - '@vitest/utils': 0.29.7 - acorn: 8.8.2 - acorn-walk: 8.2.0 - cac: 6.7.14 - chai: 4.3.7 - debug: 4.3.4 - local-pkg: 0.4.2 - pathe: 1.1.0 - picocolors: 1.0.0 - source-map: 0.6.1 - std-env: 3.3.2 - strip-literal: 1.0.0 - tinybench: 2.3.1 - tinypool: 0.4.0 - tinyspy: 1.0.2 - vite: 4.2.1(@types/node@18.15.5) - vite-node: 0.29.7(@types/node@18.15.5) - why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vitest@0.29.7(jsdom@21.1.1): - resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} - engines: {node: '>=v14.16.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - safaridriver: '*' - webdriverio: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: + playwright: optional: true safaridriver: optional: true @@ -9770,27 +9314,29 @@ packages: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 '@types/node': 18.15.5 - '@vitest/expect': 0.29.7 - '@vitest/runner': 0.29.7 - '@vitest/spy': 0.29.7 - '@vitest/utils': 0.29.7 + '@vitest/expect': 0.29.8 + '@vitest/runner': 0.29.8 + '@vitest/spy': 0.29.8 + '@vitest/ui': 0.23.4 + '@vitest/utils': 0.29.8 acorn: 8.8.2 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) + happy-dom: 8.9.0 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 picocolors: 1.0.0 source-map: 0.6.1 std-env: 3.3.2 - strip-literal: 1.0.0 - tinybench: 2.3.1 + strip-literal: 1.0.1 + tinybench: 2.4.0 tinypool: 0.4.0 tinyspy: 1.0.2 vite: 4.2.1(@types/node@18.15.5) - vite-node: 0.29.7(@types/node@18.15.5) + vite-node: 0.29.8(@types/node@18.15.5) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9799,7 +9345,7 @@ packages: - sugarss - supports-color - terser - dev: false + dev: true /vitest@0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1): resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==} @@ -9844,7 +9390,7 @@ packages: acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@5.5.0) happy-dom: 8.9.0 jsdom: 21.1.1 local-pkg: 0.4.2 @@ -9852,8 +9398,8 @@ packages: picocolors: 1.0.0 source-map: 0.6.1 std-env: 3.3.2 - strip-literal: 1.0.0 - tinybench: 2.3.1 + strip-literal: 1.0.1 + tinybench: 2.4.0 tinypool: 0.4.0 tinyspy: 1.0.2 vite: 4.2.1(@types/node@18.15.5) @@ -9866,7 +9412,6 @@ packages: - sugarss - supports-color - terser - dev: true /vscode-json-languageservice@4.2.1: resolution: {integrity: sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==} @@ -9875,7 +9420,7 @@ packages: vscode-languageserver-textdocument: 1.0.7 vscode-languageserver-types: 3.17.2 vscode-nls: 5.2.0 - vscode-uri: 3.0.6 + vscode-uri: 3.0.4 dev: false /vscode-languageserver-textdocument@1.0.7: @@ -9890,8 +9435,8 @@ packages: resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} dev: false - /vscode-uri@3.0.6: - resolution: {integrity: sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==} + /vscode-uri@3.0.4: + resolution: {integrity: sha512-aEmKD6H8Sg8gaQAUrnadG0BMeWXtiWhRsj1a94n2FYsMkDpgnK7BRVzZjOUYIvkv2B+bp5Bmt4ImZCpYbnJwkg==} dev: false /w3c-xmlserializer@4.0.0: @@ -9903,12 +9448,11 @@ packages: /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: - defaults: 1.0.4 + defaults: 1.0.3 dev: true /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -9943,7 +9487,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -9954,14 +9497,6 @@ packages: is-string: 1.0.7 is-symbol: 1.0.4 - /which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} - dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 - /which-module@2.0.0: resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} dev: true @@ -10039,18 +9574,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws@8.11.0: - resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - /ws@8.13.0: resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} engines: {node: '>=10.0.0'} @@ -10084,7 +9607,6 @@ packages: /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -10140,11 +9662,11 @@ packages: y18n: 5.0.8 yargs-parser: 20.2.9 - /yargs@17.6.2: - resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} + /yargs@17.5.1: + resolution: {integrity: sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==} engines: {node: '>=12'} dependencies: - cliui: 8.0.1 + cliui: 7.0.4 escalade: 3.1.1 get-caller-file: 2.0.5 require-directory: 2.1.1 From 2464de5dc6a2e4611b1219ed07f2d7a87345110c Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Wed, 29 Mar 2023 18:12:35 -0400 Subject: [PATCH 23/46] Forgot the first occuranec --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89e28db9..c072a601 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,6 @@ jobs: steps: - uses: actions/checkout@v2 - uses: NullVoxPopuli/action-setup-pnpm@v2 - - name: "Setup node and install dependencies" - uses: ./.github/actions/setup-node-and-install test: name: "Tests" From dcca9950e5c3035fbd0619dcb7214645d37ca75e Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Mon, 3 Apr 2023 20:50:48 -0400 Subject: [PATCH 24/46] Pin pnpm in volta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5212f34..714ae5f4 100644 --- a/package.json +++ b/package.json @@ -178,6 +178,6 @@ }, "volta": { "node": "19.8.1", - "pnpm": "8.1.0" + "pnpm": "8.1.1" } } From f9f17f357e9e0ed680df612163747e7883224279 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 4 Apr 2023 16:23:51 -0700 Subject: [PATCH 25/46] React tests pass --- packages/react/react/package.json | 2 + packages/react/react/src/context-provider.ts | 2 + packages/react/react/src/debug/warnings.ts | 4 +- packages/react/react/src/element.ts | 91 ++++--- packages/react/react/src/use-reactive.ts | 6 +- packages/react/react/src/use-resource.ts | 209 ++-------------- packages/react/react/src/use-service.ts | 16 +- packages/react/react/src/use-setup.ts | 2 + .../react/react/tests/use-reactive.spec.ts | 7 +- .../react/react/tests/use-resource.spec.ts | 4 +- .../react/react/tests/use-service.spec.ts | 110 +-------- packages/react/react/tests/use-setup.spec.ts | 6 +- packages/react/test-utils/src/modes.ts | 69 +++--- packages/universal/interfaces/index.d.ts | 2 + .../universal/interfaces/src/protocol.d.ts | 5 +- .../universal/interfaces/src/runtime.d.ts | 11 +- .../reactive/src/primitives/cached.ts | 6 +- .../universal/reactive/src/primitives/cell.ts | 4 +- .../src/primitives/formula-lifecycle.ts | 30 +-- .../reactive/src/primitives/formula.ts | 7 +- packages/universal/reactive/src/runtime.ts | 14 +- packages/universal/resource/src/api.ts | 4 +- packages/universal/runtime/index.ts | 5 - packages/universal/runtime/src/define.ts | 31 +-- .../universal/runtime/src/timeline/api.ts | 4 - .../universal/runtime/src/timeline/debug.ts | 10 + .../universal/runtime/src/timeline/frame.ts | 226 ----------------- .../universal/runtime/src/timeline/frames.ts | 149 ----------- .../runtime/src/timeline/subscriptions.ts | 69 +++++- .../runtime/src/timeline/timeline.ts | 191 --------------- .../universal/runtime/src/timeline/tracker.ts | 38 +-- .../universal/runtime/tests/consume.spec.ts | 2 +- .../runtime/tests/subscribing.spec.ts | 38 ++- .../runtime/tests/subscription.spec.ts | 19 +- packages/universal/service/src/service.ts | 3 +- packages/universal/tags/src/tag.ts | 65 ++--- packages/universal/universal/index.ts | 5 - .../universal/src/reactive-core/into.ts | 74 ------ .../universal/tests/factory.spec.todo.ts | 231 ------------------ pnpm-lock.yaml | 6 + 40 files changed, 376 insertions(+), 1401 deletions(-) delete mode 100644 packages/universal/runtime/src/timeline/api.ts create mode 100644 packages/universal/runtime/src/timeline/debug.ts delete mode 100644 packages/universal/runtime/src/timeline/frame.ts delete mode 100644 packages/universal/runtime/src/timeline/frames.ts delete mode 100644 packages/universal/runtime/src/timeline/timeline.ts delete mode 100644 packages/universal/universal/src/reactive-core/into.ts delete mode 100644 packages/universal/universal/tests/factory.spec.todo.ts diff --git a/packages/react/react/package.json b/packages/react/react/package.json index 5c6e45b0..079a208e 100644 --- a/packages/react/react/package.json +++ b/packages/react/react/package.json @@ -34,7 +34,9 @@ "@starbeam/js": "workspace:^", "@starbeam/modifier": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", + "@starbeam/service": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/use-strict-lifecycle": "workspace:^", diff --git a/packages/react/react/src/context-provider.ts b/packages/react/react/src/context-provider.ts index fad93876..29387888 100644 --- a/packages/react/react/src/context-provider.ts +++ b/packages/react/react/src/context-provider.ts @@ -18,6 +18,7 @@ export const Starbeam: FunctionComponent = ({ children }) => { const owner = prev ? ReactApp.reactivate(prev) : new ReactApp(); on.cleanup(() => { + console.log({ finalizing: owner }); owner.finalize(); }); @@ -36,6 +37,7 @@ export class ReactApp { } static reactivate(owner: ReactApp): ReactApp { + owner.#instance = {}; return owner; } diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index a637943d..97f7badc 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,11 +1,11 @@ import { Message } from "@starbeam/debug"; -import { TIMELINE } from "@starbeam/runtime"; +import { RUNTIME } from "@starbeam/runtime"; import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; if (import.meta.env.DEV) { - TIMELINE.untrackedReadBarrier((tag, stack) => { + RUNTIME.debug.untrackedReadBarrier((tag, stack) => { if (isRendering()) { if (!WARNED) { WARNED = true; diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 394b61e4..26b3ee4f 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,24 +1,22 @@ import type { browser } from "@domtree/flavors"; import { type DebugListener, Desc, type Description } from "@starbeam/debug"; import type { Reactive, Tagged } from "@starbeam/interfaces"; +import type { IntoResourceBlueprint, Resource } from "@starbeam/resource"; +import * as resource from "@starbeam/resource"; import { type CleanupTarget, + CONTEXT, LIFETIME, type OnCleanup, PUBLIC_TIMELINE, type Unsubscribe, } from "@starbeam/runtime"; -import { - type Cell, - createService, - Factory, - type IntoResource, -} from "@starbeam/universal"; +import { service } from "@starbeam/service"; +import { Cell, PolledFormula } from "@starbeam/universal"; import { ReactApp } from "./context-provider.js"; import { missingApp } from "./context-provider.js"; import { type ElementRef, type ReactElementRef, ref } from "./ref.js"; -import { MountedResource } from "./use-resource.js"; // eslint-disable-next-line @typescript-eslint/no-explicit-any type AnyRecord = Record; @@ -236,9 +234,9 @@ export class ReactiveElement implements CleanupTarget { } service = ( - factory: IntoResource, + blueprint: IntoResourceBlueprint, description?: string | Description | undefined - ): Reactive => { + ): Resource => { const desc = Desc("service", description); const context = this.#context; @@ -246,39 +244,70 @@ export class ReactiveElement implements CleanupTarget { missingApp(`service()`); } - return createService(factory, desc, ReactApp.instance(context)); + CONTEXT.app = ReactApp.instance(context); + + return service(blueprint, desc); }; - use = ( - factory: IntoResource, - options?: { initial?: T; description: string | Description | undefined } - ): Reactive => { - const desc = Desc("resource", options?.description); - const resource = MountedResource.create(options?.initial, desc); + use = ( + factory: IntoResourceBlueprint, + options?: { initial?: T } + ): Reactive => { + return internalUseResource( + this, + { + notify: this.notify, + on: { + layout: (callback) => + this.on.layout(() => { + callback(factory); + }), + cleanup: this.on.cleanup, + }, + }, + options?.initial + ); + }; - LIFETIME.link(this, resource); + refs(refs: R): RefsRecordFor { + const { refs: newRefs, record } = this.#refs.update(refs); - const create = (): void => { - resource.create((owner) => Factory.resource(factory, owner)); + this.#refs = newRefs; + return record; + } +} +interface ResourceHost { + readonly notify: () => void; + readonly on: { + layout: (callback: (value: T) => void) => Unsubscribe | void; + cleanup: (callback: () => void) => Unsubscribe | void; + }; +} - this.notify(); - }; +export function internalUseResource( + lifetime: object, + host: ResourceHost>, + initial: T | undefined +): Reactive { + let unsubscribe: Unsubscribe | undefined = undefined; + const resourceCell = Cell(undefined as undefined | Resource); - const unsubscribe = PUBLIC_TIMELINE.on.change(resource, this.notify); + const create = (blueprint: IntoResourceBlueprint): void => { + resourceCell.set(resource.use(blueprint, { lifetime })); - LIFETIME.on.cleanup(resource, unsubscribe); + host.notify(); + }; - this.on.layout(create); + host.on.layout(create); - return resource as Reactive; - }; + const formula = PolledFormula(() => { + return (resourceCell.current?.current as T | undefined) ?? initial; + }); - refs(refs: R): RefsRecordFor { - const { refs: newRefs, record } = this.#refs.update(refs); + unsubscribe = PUBLIC_TIMELINE.on.change(formula, host.notify); + host.on.cleanup(unsubscribe); - this.#refs = newRefs; - return record; - } + return formula; } type Callback = diff --git a/packages/react/react/src/use-reactive.ts b/packages/react/react/src/use-reactive.ts index 57a17dd3..66023adf 100644 --- a/packages/react/react/src/use-reactive.ts +++ b/packages/react/react/src/use-reactive.ts @@ -1,11 +1,11 @@ -import { type Description, Desc } from "@starbeam/debug"; +import { Desc, type Description } from "@starbeam/debug"; +import { PUBLIC_TIMELINE } from "@starbeam/runtime"; import type { Reactive } from "@starbeam/universal"; import { Cell, Formula, LIFETIME, PolledFormula, - TIMELINE, Wrap, } from "@starbeam/universal"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; @@ -47,7 +47,7 @@ export function useReactive( // We wait until the first layout to subscribe to the formula, because React will // only guarantee that the cleanup function is called after the first layout. on.layout(() => { - const unsubscribe = TIMELINE.on.change(formula, notify); + const unsubscribe = PUBLIC_TIMELINE.on.change(formula, notify); on.cleanup(unsubscribe); }); diff --git a/packages/react/react/src/use-resource.ts b/packages/react/react/src/use-resource.ts index e49a5e5b..a733ad21 100644 --- a/packages/react/react/src/use-resource.ts +++ b/packages/react/react/src/use-resource.ts @@ -1,62 +1,34 @@ -import { Desc, type Description } from "@starbeam/debug"; -import { LIFETIME, TIMELINE } from "@starbeam/runtime"; -import { - Cell, - Factory, - Formula, - type IntoResource, - type Reactive, - type ResourceBlueprint, - Wrap, -} from "@starbeam/universal"; +import { type Description } from "@starbeam/debug"; +import type { IntoResourceBlueprint } from "@starbeam/resource"; +import { LIFETIME } from "@starbeam/runtime"; +import { type Reactive } from "@starbeam/universal"; import { unsafeTrackedElsewhere, useLifecycle, } from "@starbeam/use-strict-lifecycle"; +import { internalUseResource } from "./element.js"; import { useNotify } from "./use-reactive.js"; -export type UseFactory = - | ResourceBlueprint - | (() => IntoResource); - -export function use( - factory: - | ResourceBlueprint - | (() => ResourceBlueprint), - dependencies?: unknown[] -): T | Initial; export function use( - factory: ResourceBlueprint | (() => ResourceBlueprint), - options: { initial?: T; description?: string | Description | undefined }, - dependencies?: unknown[] -): T; -export function use( - factory: ResourceBlueprint | (() => ResourceBlueprint), - options: { description?: string | Description | undefined } -): T | Initial; -export function use( - factory: IntoResource, + factory: IntoResourceBlueprint, options?: | { initial?: T; description?: string | Description | undefined } | unknown[], dependencies?: unknown[] ): T | undefined { const value = createResource( - factory as IntoResource, + factory as IntoResourceBlueprint, options, dependencies ); - const result = unsafeTrackedElsewhere(() => value.current); - return result; + return unsafeTrackedElsewhere(() => value.current); } function createResource( - factory: IntoResource, - options?: - | { initial?: T; description?: string | Description | undefined } - | unknown[], + factory: IntoResourceBlueprint, + options?: { initial?: T } | unknown[], dependencies?: unknown[] ): Reactive { const notify = useNotify(); @@ -64,170 +36,37 @@ function createResource( function normalize(): { deps: unknown[]; initialValue: T | undefined; - description: string | Description | undefined; } { if (Array.isArray(options)) { - return { deps: options, initialValue: undefined, description: undefined }; + return { deps: options, initialValue: undefined }; } else { return { deps: dependencies ?? [], initialValue: options?.initial, - description: options?.description, }; } } - const { deps, initialValue, description } = normalize(); - const desc = Desc("resource", description); - - // We pass `deps` and `factory` as the `useLifecycle` arguments. This means that `useLifecycle` - // callbacks will receive up-to-date values for `deps` and `factory` when they're called. This - // is especially important for `update`, which runs on every render: if the deps have changed in a - // particular render, we need to use an up-to-date `factory` to create the resource. - const cell = useLifecycle({ props: factory, validate: deps }).render< - Cell> - >(({ on, validate }, _, prev) => { - const cell = prev ?? Cell(undefined as unknown); - - // Create a new instance of `LastResource` for this mount. It will remain stable until the - // component is unmounted (even temporarily), at which point it will be finalized. This means - // that **re***-renders, which call the `update` callback, will share the same `LastResource` - // instance. - const resource = MountedResource.create(initialValue as T, desc); - - // When React unmounts the component (even temporarily), we finalize the resource. - on.cleanup(() => { - LIFETIME.finalize(resource); - }); - - // This function is called to instantiate the resource. It's called in two circumstances: - // - // 1. When the factory is first created, and - // 2. When the dependencies change. - // - // React runs the render function twice in strict mode (without running effects or cleanup in - // between). This means that any state that requires cleanup must be created in a React effect, - // or it will leak. - // - // The resource is initially created in an effect (which guarantees that React will run its - // cleanup function when the component is unmounted). When the resource's dependencies change, - // we need to reset the resource. In that situation, we know that the component's - // effects have already run, so we clean up the previous resource and create a new one in the - // call to `use`. - // - // In practice, this means that `use` returns the initial value (which defaults to `undefined`) - // during the initial render, but always returns the current value of the resource after that. - function create(factory: IntoResource): void { - // Create the resource. The resource is created with the `lastResource` as its owner. This - // means that the resource will be finalized when `lastResource` is finalized, which happens - // (above) when the component is unmounted. - resource.create((owner) => Factory.resource(factory, owner)); - - // `value` is initialized below. It's a formula that returns the current value of the - // resource (or its initial value). Whenever that value changes, we notify React. - const unsubscribe = TIMELINE.on.change(resource, () => { - notify(); - }); - - // When the resource is finalized (because the component is unmounted, even temporarily), we - // unsubscribe from the resource's changes. This is largely for hygiene, but it also prevents - // us from (unnecessarily) notifying React after the component has been unmounted. - // - // If the component is remounted, we'll get a whole new `useLifecycle` instance, which will - // create a new `lastResource` and a new `value` formula. TL;DR From the perspective of this - // code, "mounting" and "remounting" are the same thing. - LIFETIME.on.cleanup(resource, unsubscribe); - - // Now that we've created the resource, we can notify React that the component has updated. - // Since we haven't yet consumed the `value` formula, it doesn't yet have any dependencies. - // Notifying React will cause React to run the component's render function again, which will - // consume the `value` formula (and keep it up to date). - notify(); - } - - // When the component is first rendered, we wait until React commits the component to create the - // resource. This is because React can render the component and never run effects. So we defer - // the creation of the resource until React commits the component. - on.layout((factory) => { - create(factory); - }); + const { deps, initialValue } = normalize(); + return useLifecycle({ props: factory, validate: deps }).render< + Reactive + >(({ on, validate }, _) => { validate(sameDeps); - cell.set(resource); - return cell as Cell>; - }); - - return unsafeTrackedElsewhere(() => cell.current); -} - -export class MountedResource { - static create( - initial: T, - description: Description - ): MountedResource & Reactive { - const resource = new MountedResource(initial, description); - return Wrap(resource.formula, resource); - } - - readonly formula: Formula; - readonly #initial: T; - readonly #cell: Cell | undefined>; - #value: Reactive | undefined; - #owner: object | undefined = undefined; - - private constructor(initial: T, description: Description) { - this.#initial = initial; - this.#cell = Cell(undefined as Reactive | undefined, { - description: description.implementation("target"), - }); - this.#value = undefined; - this.formula = Formula( - () => this.#cell.current?.current ?? this.#initial, - description.implementation("formula") + const lifetime = {}; + const resource = internalUseResource( + lifetime, + { on, notify }, + initialValue ); - LIFETIME.on.cleanup(this, () => { - this.#finalize(); + on.cleanup(() => { + LIFETIME.finalize(lifetime); }); - } - - #finalize(): void { - if (this.#owner) { - LIFETIME.finalize(this.#owner); - this.#owner = undefined; - } - } - - #reset(): object { - this.#finalize(); - this.#owner = {}; - LIFETIME.link(this, this.#owner); - return this.#owner; - } - - isInactive(): boolean { - return this.#value === undefined; - } - - create(factory: (owner: object) => Reactive): { - reactive: Reactive; - owner: object; - } { - const owner = this.#reset(); - - const reactive = factory(owner); - - this.#cell.set(reactive); - this.#value = reactive; - - // If the `use`d resource is finalized, and the return value of the factory is a resource, we - // want to finalize that resource as well. - LIFETIME.link(this, reactive); - - return { reactive, owner }; - } + return resource; + }); } export function sameDeps( diff --git a/packages/react/react/src/use-service.ts b/packages/react/react/src/use-service.ts index 5190097a..4b7ba84b 100644 --- a/packages/react/react/src/use-service.ts +++ b/packages/react/react/src/use-service.ts @@ -1,18 +1,20 @@ +import type { ReadValue } from "@starbeam/reactive"; +import type { IntoResourceBlueprint } from "@starbeam/resource"; import { CONTEXT } from "@starbeam/runtime"; -import { - type Blueprint, - type ResourceFactory, - service, -} from "@starbeam/universal"; +import { service } from "@starbeam/service"; import { ReactApp, useStarbeamApp } from "./context-provider.js"; import { useReactive } from "./use-reactive.js"; -export function useService(factory: Blueprint | ResourceFactory): T { +export function useService( + blueprint: IntoResourceBlueprint +): ReadValue { CONTEXT.app = ReactApp.instance(useStarbeamApp({ feature: "useService()" })); + const instance = service(blueprint); + // We don't want to instantiate the service as a resource, because that would // cause it to be cleaned up when the component unmounts. Instead, we want to // keep it alive for the lifetime of the app. - return useReactive(() => service(factory)); + return useReactive(() => instance.current); } diff --git a/packages/react/react/src/use-setup.ts b/packages/react/react/src/use-setup.ts index 924233b0..48390d45 100644 --- a/packages/react/react/src/use-setup.ts +++ b/packages/react/react/src/use-setup.ts @@ -82,7 +82,9 @@ export function useSetup< const reactive = PolledFormula(() => { return (instance as (props: unknown) => unknown)(currentProps); }, desc); + ReactiveElement.subscribe(element, reactive); + function compute(props: unknown, caller = callerStack()): unknown { currentProps = props; return reactive.read(caller); diff --git a/packages/react/react/tests/use-reactive.spec.ts b/packages/react/react/tests/use-reactive.spec.ts index 4a6b1929..8ccaf8ee 100644 --- a/packages/react/react/tests/use-reactive.spec.ts +++ b/packages/react/react/tests/use-reactive.spec.ts @@ -3,8 +3,8 @@ import { useReactive, useSetup } from "@starbeam/react"; import { Cell, Formula } from "@starbeam/universal"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; +import { describe, expect } from "@starbeam-workspace/test-utils"; import { useState } from "react"; -import { describe, expect } from "vitest"; const INITIAL_ID = 0; const INITIAL_COUNT = 0; @@ -229,12 +229,17 @@ describe("useReactive", () => { }).compute(); }); + console.log("initial"); expect(result.value).toEqual({ starbeam: 0, react: 0 }); + console.log("clicking starbeam"); await result.findByText("++Starbeam++").fire.click(); + console.log("clicked starbeam"); expect(result.value).toEqual({ starbeam: 1, react: 0 }); + console.log("clicked react"); await result.findByText("++React++").fire.click(); + console.log("clicked react"); expect(result.value).toEqual({ starbeam: 1, react: 1 }); } ); diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index 8e8e321f..91fd0192 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -12,7 +12,7 @@ import { type ResourceBlueprint, } from "@starbeam/universal"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; -import { beforeEach, describe, expect } from "vitest"; +import { beforeEach, describe, expect } from "@starbeam-workspace/test-utils"; import { Channel } from "./support/channel.js"; @@ -420,7 +420,7 @@ function send(message: string): void { function ChannelResource( name: IntoReactive -): ResourceBlueprint { +): ResourceBlueprint { const reactive = intoReactive(name); return Resource((r) => { diff --git a/packages/react/react/tests/use-service.spec.ts b/packages/react/react/tests/use-service.spec.ts index 3bfea34e..5710e3d3 100644 --- a/packages/react/react/tests/use-service.spec.ts +++ b/packages/react/react/tests/use-service.spec.ts @@ -1,7 +1,7 @@ // @vitest-environment jsdom import { callerStack, entryPoint } from "@starbeam/debug"; -import { Starbeam, useService, useSetup } from "@starbeam/react"; +import { Starbeam, useService } from "@starbeam/react"; import { Cell, Resource } from "@starbeam/universal"; import type { RenderState } from "@starbeam-workspace/react-test-utils"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; @@ -114,113 +114,6 @@ describe("services", () => { result.unmount(); expect(channel?.isActive).toBe(false); }); - - testReact<{ name: string }, Auth | null>( - "service in useSetup", - async (root) => { - const result = await root - .expectHTML((auth) => - auth - ? `${auth.username}` - : `

    loading

    ` - ) - .render( - (state) => { - return createElement( - Starbeam, - null, - react.render(Profile, { - testState: state, - }) - ); - }, - { name: "test" } - ); - - function Avatar(): React.ReactElement | null { - const user = useSetup(({ service }) => service(CurrentUser)); - - return user ? html.img({ src: user.avatar }) : null; - } - - function Username(): React.ReactElement | null { - const user = useSetup(({ service }) => service(CurrentUser)); - - return user ? html.span(user.username) : null; - } - - function Profile({ - testState, - }: { - testState: RenderState; - }): React.ReactElement { - testState.rendered(); - const user = useSetup(({ service }) => service(CurrentUser)); - - testState.value(user); - - if (user) { - return react.fragment(react.render(Avatar), react.render(Username)); - } else { - return html.p("loading"); - } - } - - async function send( - message: Auth, - options: { expect: "active" | "inactive" } = { expect: "active" }, - caller = callerStack() - ): Promise { - await result.act(() => { - const latest = AUTH_CHANNELS.latest(); - - if (latest === undefined) { - entryPoint( - () => { - expect(latest, "Channel.latest()").not.toBeUndefined(); - }, - { stack: caller } - ); - return; - } - - AUTH_CHANNELS.sendMessage(latest, message); - }, caller); - - entryPoint( - () => { - expect( - channel?.isActive, - `the channel should be ${options.expect}` - ).toBe(options.expect === "active"); - - expect(result.value, "the last rendered auth value").toEqual({ - ...message, - }); - }, - { stack: caller } - ); - } - - const channel = AUTH_CHANNELS.latest(); - expect( - channel, - "After rendering, the channel exists" - ).not.toBeUndefined(); - - expect(result.value).toBe(null); - await send({ username: "elwayman02", avatar: "jordan.fake.png" }); - - await result.rerender(); - - await send({ username: "elwayman02", avatar: "jordan2.fake.png" }); - await send({ username: "elwayman02", avatar: "jordan3.fake.png" }); - - // services should be cleaned up when the root component is unmounted - result.unmount(); - expect(channel?.isActive).toBe(false); - } - ); }); interface Auth { @@ -232,6 +125,7 @@ const CurrentUser = Resource((r) => { const lastMessage = Cell(null as Auth | null, "last message"); const c = AUTH_CHANNELS.subscribe("auth"); + console.log({ c, latest: AUTH_CHANNELS.latest() }); c.onMessage((message) => { lastMessage.set(message); diff --git a/packages/react/react/tests/use-setup.spec.ts b/packages/react/react/tests/use-setup.spec.ts index 7ec6a101..9d9ca165 100644 --- a/packages/react/react/tests/use-setup.spec.ts +++ b/packages/react/react/tests/use-setup.spec.ts @@ -5,8 +5,8 @@ import type { ReactiveElement } from "@starbeam/react"; import { useReactive, useSetup } from "@starbeam/react"; import { Cell } from "@starbeam/universal"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; +import { describe, expect } from "@starbeam-workspace/test-utils"; import type { ReactElement } from "react"; -import { describe, expect } from "vitest"; import { Channels } from "./support/channel.js"; @@ -164,7 +164,9 @@ describe("useSetup", () => { return react.fragment( html.span(reactiveState.state), - reactiveState.state === "message" ? html.span(reactiveState.lastMessage) : null + reactiveState.state === "message" + ? html.span(reactiveState.lastMessage) + : null ); }); diff --git a/packages/react/test-utils/src/modes.ts b/packages/react/test-utils/src/modes.ts index 2dab37e4..0d88a72c 100644 --- a/packages/react/test-utils/src/modes.ts +++ b/packages/react/test-utils/src/modes.ts @@ -252,58 +252,49 @@ export class SetupTestRoot { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types props?: any ): Promise> { - const result = entryPoint( - () => { - const state = new RenderState(); - let i = 0; - - const Component = (props: any): ReactElement => { - state.rendered(); - return render(state, props); - }; - - const result = act(() => - testing.render( - react.render(Component, { ...props, rerender: ++i }), - this.#options - ) - ); + const state = new RenderState(); + let i = 0; - const renderResult = new RenderResult( - this, - state, - result, - props, - (updatedProps?: any) => { - if (updatedProps) { - result.rerender( - react.render(Component, { ...updatedProps, rerender: ++i }) - ); - } else { - result.rerender( - react.render(Component, { ...props, rerender: ++i }) - ); - } - } - ); + const Component = (props: any): ReactElement => { + state.rendered(); + return render(state, props); + }; - return renderResult; - }, - { internal: 1 } - ) as unknown as RenderResult; + const result = act(() => + testing.render( + react.render(Component, { ...props, rerender: ++i }), + this.#options + ) + ); + + const renderResult = new RenderResult( + this, + state, + result, + props, + (updatedProps?: any) => { + if (updatedProps) { + result.rerender( + react.render(Component, { ...updatedProps, rerender: ++i }) + ); + } else { + result.rerender(react.render(Component, { ...props, rerender: ++i })); + } + } + ); entryPoint( () => { SetupTestRoot.assert( this as unknown as SetupTestRoot, - result, + renderResult, props as Props ); }, { internal: 1 } ); - return Promise.resolve(result); + return Promise.resolve(renderResult); } expectHTML(expectHtml: (value: T, props: Props) => string): this { diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index a32fe068..4d0ae996 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -40,6 +40,7 @@ export type { ReactiveValue, SpecificTag, StaticTag, + SubscriptionTarget, Tag, Tagged, TaggedReactive, @@ -49,6 +50,7 @@ export type { export type { ActiveFrame, AutotrackingRuntime, + DebugRuntime, DeprecatedTimeline, Runtime, RuntimeFrame, diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.d.ts index 09d4a64d..c1165357 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.d.ts @@ -16,7 +16,7 @@ export interface AbstractTag { * This avoids subscribing to a formula without computing its value, which is * a violation of the tag contract. */ - readonly tdz: boolean; + readonly initialized: boolean; } export type List = Iterable | T[] | readonly T[]; @@ -26,8 +26,8 @@ export class TagMethods { readonly lastUpdated: Timestamp; readonly dependencies: () => readonly CellTag[]; readonly description: Description; + readonly subscriptionTargets: readonly SubscriptionTarget[]; match(matcher: Matcher): Tag; - subscriptionTargets(): List; } export type ExhaustiveMatcher = { @@ -118,6 +118,7 @@ export interface StaticTag extends AbstractTag, TagMethods { * they are, and that generality breaks system invariants derived from value composition. */ export type Tag = CellTag | FormulaTag | DelegateTag | StaticTag; +export type SubscriptionTarget = CellTag | FormulaTag; export type TagType = Tag["type"]; export type SpecificTag = Extract; diff --git a/packages/universal/interfaces/src/runtime.d.ts b/packages/universal/interfaces/src/runtime.d.ts index 7c1942bb..6647bed0 100644 --- a/packages/universal/interfaces/src/runtime.d.ts +++ b/packages/universal/interfaces/src/runtime.d.ts @@ -13,18 +13,23 @@ export interface DeprecatedTimeline { export interface Runtime { callerStack: () => CallStack; - /** @deprecated */ - readonly timeline: DeprecatedTimeline; readonly subscriptions: SubscriptionRuntime; readonly autotracking: AutotrackingRuntime; + readonly debug: DebugRuntime; } export interface SubscriptionRuntime { subscribe: (target: Tag, ready: NotifyReady) => Unsubscribe; - bump: (cell: CellTag) => Timestamp; + bump: (cell: CellTag) => { revision: Timestamp; notify: () => void }; update: (formula: FormulaTag) => void; } +export interface DebugRuntime { + untrackedReadBarrier: ( + barrier: (tag: Tag, stack: CallStack) => void | never + ) => void; +} + export type ActiveFrame = () => Set; export interface AutotrackingRuntime { diff --git a/packages/universal/reactive/src/primitives/cached.ts b/packages/universal/reactive/src/primitives/cached.ts index d1d896de..b9696ba3 100644 --- a/packages/universal/reactive/src/primitives/cached.ts +++ b/packages/universal/reactive/src/primitives/cached.ts @@ -41,7 +41,7 @@ class FormulaImpl implements ReactiveFormula { this.#compute = compute; this[TAG] = FormulaTag.create(description, () => { if (this.#last === null) return []; - return this.#last.formula[TAG].children(); + return this.#last.formula.children(); }); } @@ -75,8 +75,8 @@ class FormulaImpl implements ReactiveFormula { value, }; - // Allow the formula to be subscribed to. - this[TAG].unsetTdz(); + this[TAG].markInitialized(); + RUNTIME.subscriptions.update(this[TAG]); return value; } diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index 8a1b6feb..500f42e7 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -20,7 +20,7 @@ export class CellImpl implements ReactiveCell { static create = ( value: T, options?: CellOptions | DescriptionOption - ): CellImpl => { + ): Cell => { const { description, equals = Object.is } = toCellOptions(options); return new CellImpl(value, equals, Desc("cell", description)); }; @@ -71,7 +71,7 @@ export class CellImpl implements ReactiveCell { } export const Cell = CellImpl.create; -export type Cell = Expand>; +export type Cell = CellImpl; export type Equality = (a: T, b: T) => boolean; diff --git a/packages/universal/reactive/src/primitives/formula-lifecycle.ts b/packages/universal/reactive/src/primitives/formula-lifecycle.ts index 8a4c556b..df63cbe6 100644 --- a/packages/universal/reactive/src/primitives/formula-lifecycle.ts +++ b/packages/universal/reactive/src/primitives/formula-lifecycle.ts @@ -3,12 +3,10 @@ import type { ActiveFrame, Description, Expand, - Tagged, Timestamp, } from "@starbeam/interfaces"; import type { Tag } from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; -import { FormulaTag, NOW } from "@starbeam/tags"; +import { NOW, TagUtils } from "@starbeam/tags"; import { getRuntime } from "../runtime.js"; import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; @@ -29,7 +27,7 @@ export class InitializingFormulaImpl { } done(): FinalizedFormula { - return new FinalizedFormulaImpl(this.#active(), NOW.now, this.#description); + return new FinalizedFormulaImpl(this.#active(), NOW.now); } } @@ -37,30 +35,25 @@ export const FormulaLifecycle = InitializingFormulaImpl.start; export type InitializingFormula = Expand; export type FinalizedFormula = Expand; -class FinalizedFormulaImpl implements Tagged { - static create = ( - children: Set, - description: Description - ): FinalizedFormula => { - return new FinalizedFormulaImpl(children, NOW.now, description); +class FinalizedFormulaImpl { + static create = (children: Set): FinalizedFormula => { + return new FinalizedFormulaImpl(children, NOW.now); }; #children: Set; #lastValidated: Timestamp; - declare readonly [TAG]: FormulaTag; - constructor( - children: Set, - lastValidated: Timestamp, - description: Description - ) { + constructor(children: Set, lastValidated: Timestamp) { this.#children = children; this.#lastValidated = lastValidated; - this[TAG] = FormulaTag.create(description, () => this.#children); } isStale(): boolean { - return this[TAG].lastUpdated.gt(this.#lastValidated); + return TagUtils.lastUpdatedIn(this.#children).gt(this.#lastValidated); + } + + children(): Set { + return this.#children; } update(): { done: () => void } { @@ -70,7 +63,6 @@ class FinalizedFormulaImpl implements Tagged { done: () => { this.#children = done(); this.#lastValidated = NOW.now; - getRuntime().subscriptions.update(this[TAG]); }, }; } diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts index c7f079a4..ccb53696 100644 --- a/packages/universal/reactive/src/primitives/formula.ts +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -40,11 +40,8 @@ export class FormulaImpl const { value, tags } = RUNTIME.evaluate(this.#compute); this.#children = tags; - if (this[TAG].tdz) { - this[TAG].unsetTdz(); - } else { - RUNTIME.subscriptions.update(this[TAG]); - } + this[TAG].markInitialized(); + RUNTIME.subscriptions.update(this[TAG]); return value; } diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index a8d02dfb..dead5662 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -1,6 +1,6 @@ import type { AutotrackingRuntime, - DeprecatedTimeline, + DebugRuntime, Runtime, Stack, SubscriptionRuntime, @@ -32,10 +32,6 @@ class RuntimeImpl implements Runtime { return getRuntime().callerStack(); } - get timeline(): DeprecatedTimeline { - return getRuntime().timeline; - } - get subscriptions(): SubscriptionRuntime { return getRuntime().subscriptions; } @@ -44,16 +40,16 @@ class RuntimeImpl implements Runtime { return getRuntime().autotracking; } + get debug(): DebugRuntime { + return getRuntime().debug; + } + evaluate(compute: () => T): { value: T; tags: Set } { const done = this.autotracking.start(); const value = compute(); const tags = done(); return { value, tags }; } - - // timeline: DeprecatedTimeline; - // subscriptions: SubscriptionRuntime; - // autotracking: AutotrackingRuntime; } export const RUNTIME = new RuntimeImpl(); diff --git a/packages/universal/resource/src/api.ts b/packages/universal/resource/src/api.ts index c064b4d5..9aa4cf00 100644 --- a/packages/universal/resource/src/api.ts +++ b/packages/universal/resource/src/api.ts @@ -37,8 +37,8 @@ export const Resource = ResourceBlueprintImpl.create; export { isResource } from "./resource.js"; export type ResourceBlueprint = - | ResourceBlueprintImpl - | ResourceBlueprintImpl, void>; + | ResourceBlueprintImpl, void> + | ResourceBlueprintImpl; export type IntoResourceBlueprint = | ResourceBlueprint diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index 15063e4e..51ad8d64 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -6,11 +6,6 @@ export { type OnCleanup, } from "./src/lifetime/api.js"; export type { Unsubscribe } from "./src/lifetime/object-lifetime.js"; -export { - ActiveFrame, - Frame, - type FrameValidation, -} from "./src/timeline/frame.js"; export { type NotifyReady, Subscriptions, diff --git a/packages/universal/runtime/src/define.ts b/packages/universal/runtime/src/define.ts index 57ef6642..41f8bdec 100644 --- a/packages/universal/runtime/src/define.ts +++ b/packages/universal/runtime/src/define.ts @@ -1,57 +1,60 @@ import { callerStack } from "@starbeam/debug"; import type { AutotrackingRuntime, + DebugRuntime, Runtime as IRuntime, Stack, SubscriptionRuntime, } from "@starbeam/interfaces"; import { defineRuntime } from "@starbeam/reactive"; -import { TIMELINE } from "./timeline/api.js"; +import { DEBUG_RUNTIME } from "./timeline/debug.js"; import { SUBSCRIPTION_RUNTIME } from "./timeline/tracker.js"; import { AUTOTRACKING_RUNTIME } from "./tracking-stack.js"; -type Timeline = typeof TIMELINE; - class Runtime implements IRuntime { static default(): Runtime { - return new Runtime(TIMELINE, SUBSCRIPTION_RUNTIME, AUTOTRACKING_RUNTIME); + return new Runtime( + SUBSCRIPTION_RUNTIME, + AUTOTRACKING_RUNTIME, + DEBUG_RUNTIME + ); } static single( - runtime: Timeline & SubscriptionRuntime & AutotrackingRuntime + runtime: SubscriptionRuntime & AutotrackingRuntime & DebugRuntime ): Runtime { return new Runtime(runtime, runtime, runtime); } static create({ - timeline, subscriptions, autotracking, + debug, }: { - timeline: Timeline; subscriptions: SubscriptionRuntime; autotracking: AutotrackingRuntime; + debug: DebugRuntime; }): Runtime { - return new Runtime(timeline, subscriptions, autotracking); + return new Runtime(subscriptions, autotracking, debug); } - readonly #timeline: Timeline; readonly #subscriptions: SubscriptionRuntime; readonly #autotracking: AutotrackingRuntime; + readonly #debug: DebugRuntime; private constructor( - timeline: Timeline, subscription: SubscriptionRuntime, - autotracking: AutotrackingRuntime + autotracking: AutotrackingRuntime, + debug: DebugRuntime ) { - this.#timeline = timeline; this.#subscriptions = subscription; this.#autotracking = autotracking; + this.#debug = debug; } - get timeline(): Timeline { - return this.#timeline; + get debug(): DebugRuntime { + return this.#debug; } get subscriptions(): SubscriptionRuntime { diff --git a/packages/universal/runtime/src/timeline/api.ts b/packages/universal/runtime/src/timeline/api.ts deleted file mode 100644 index 5a752fdf..00000000 --- a/packages/universal/runtime/src/timeline/api.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Timeline } from "./timeline.js"; - -/** @deprecated */ -export const TIMELINE = Timeline.create(); diff --git a/packages/universal/runtime/src/timeline/debug.ts b/packages/universal/runtime/src/timeline/debug.ts new file mode 100644 index 00000000..3c04f54f --- /dev/null +++ b/packages/universal/runtime/src/timeline/debug.ts @@ -0,0 +1,10 @@ +import type * as interfaces from "@starbeam/interfaces"; +export class DebugRuntime implements interfaces.DebugRuntime { + untrackedReadBarrier( + _barrier: (tag: interfaces.Tag, stack: interfaces.Stack) => void | never + ): void { + /* ... */ + } +} + +export const DEBUG_RUNTIME = new DebugRuntime(); diff --git a/packages/universal/runtime/src/timeline/frame.ts b/packages/universal/runtime/src/timeline/frame.ts deleted file mode 100644 index 30dc9b9d..00000000 --- a/packages/universal/runtime/src/timeline/frame.ts +++ /dev/null @@ -1,226 +0,0 @@ -import type { - Description, - Frame as IFrame, - Tagged, - Timestamp, -} from "@starbeam/interfaces"; -import type * as interfaces from "@starbeam/interfaces"; -import { TAG, UNINITIALIZED } from "@starbeam/shared"; -import { CellTag, FormulaTag, getNow, getTag, Tag } from "@starbeam/tags"; -import { isNotEqual, verified } from "@starbeam/verify"; - -import type { FrameStack } from "./frames.js"; -import { getID } from "./id.js"; -import type { Timeline } from "./timeline.js"; - -interface Marker { - [TAG]: Omit & { - lastUpdated: Timestamp; - }; -} - -export class Frame - implements Tagged, IFrame -{ - static create( - this: void, - value: T, - children: Set, - finalized: Timestamp, - description: Description - ): Frame { - const id = getID(); - - return new Frame( - value, - { - [TAG]: CellTag.create( - description.key("initialized?", { id }).asImplementation(), - finalized - ), - }, - children, - finalized, - description - ); - } - - static uninitialized( - finalized: Timestamp, - description: Description - ): Frame { - const id = description.id; - - return new Frame( - UNINITIALIZED, - { - [TAG]: CellTag.create( - description.detail("initialized?", { id }), - finalized - ), - }, - new Set(), - finalized, - description - ); - } - - static value(this: void, frame: Frame): T { - return verified(frame.#value, isNotEqual(UNINITIALIZED)); - } - - static isInitialized(this: void, frame: Frame): boolean { - return frame.#value !== UNINITIALIZED; - } - - static update( - this: void, - frame: Frame, - value: T, - children: Set, - finalized: Timestamp - ): Frame { - return frame.#update(value, children, finalized); - } - - static updateChildren( - this: void, - frame: Frame, - children: Set - ): void { - frame.#children = children; - } - - #value: T | UNINITIALIZED; - readonly #initialized: Marker; - #children: ReadonlySet; - #finalized: Timestamp; - readonly #description: Description; - readonly [TAG]: FormulaTag; - - constructor( - value: T | UNINITIALIZED, - initialized: { - [TAG]: Omit & { - lastUpdated: Timestamp; - }; - }, - children: Set, - finalized: Timestamp, - description: Description - ) { - this.#value = value; - this.#initialized = initialized; - this.#children = children; - this.#finalized = finalized; - this.#description = description; - this[TAG] = FormulaTag.create(this.#description, () => [ - getTag(this.#initialized), - ...this.#children, - ]); - } - - get description(): Description { - return this.#description; - } - - evaluate(block: () => T, stack: FrameStack): Frame { - const activeFrame = stack.start(this); - - try { - stack.willEvaluate(); - const result = block(); - const frame = stack.end(activeFrame, result); - stack.updateSubscriptions(frame); - return frame; - } catch (e) { - stack.finally(activeFrame); - throw e; - } - } - - #update(value: T, children: Set, finalized: Timestamp): this { - if (Object.is(this.#value, UNINITIALIZED)) { - this.#initialized[TAG].lastUpdated = finalized; - } - - this.#value = value; - this.#children = children; - this.#finalized = finalized; - return this; - } - - validate(): FrameValidation> { - if ( - this.#value === UNINITIALIZED || - Tag.lastUpdatedIn(this.#children).gt(this.#finalized) - ) { - return { status: "invalid" }; - } else { - return { - status: "valid", - value: this.#value as Exclude, - }; - } - } -} - -export class ActiveFrame { - static create( - updating: Frame | null, - prev: ActiveFrame | null, - description: Description - ): ActiveFrame { - return new ActiveFrame(updating, prev, new Set(), description); - } - - readonly #updating: Frame | null; - readonly #prev: ActiveFrame | null; - readonly #children: Set; - - private constructor( - updating: Frame | null, - prev: ActiveFrame | null, - children: Set, - readonly description: Description - ) { - this.#updating = updating; - this.#prev = prev; - this.#children = children; - } - - add(child: interfaces.Tag): void { - this.#children.add(child); - } - - finally(): { prev: ActiveFrame | null } { - return { prev: this.#prev }; - } - - finalize( - value: T, - timeline: Timeline - ): { prev: ActiveFrame | null; frame: Frame } { - let frame = this.#updating; - - if (frame) { - Frame.update(frame, value, this.#children, getNow()); - timeline.update(frame); - } else { - frame = Frame.create(value, this.#children, getNow(), this.description); - } - - return { prev: this.#prev, frame }; - } -} - -export interface ValidFrame { - readonly status: "valid"; - readonly value: T; -} - -export interface InvalidFrame { - readonly status: "invalid"; -} - -export type FrameValidation = ValidFrame | InvalidFrame; diff --git a/packages/universal/runtime/src/timeline/frames.ts b/packages/universal/runtime/src/timeline/frames.ts deleted file mode 100644 index b141907e..00000000 --- a/packages/universal/runtime/src/timeline/frames.ts +++ /dev/null @@ -1,149 +0,0 @@ -import type { DebugTimeline, Stack } from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; -import type { CellTag } from "@starbeam/interfaces"; -import { getTag } from "@starbeam/tags"; - -import { ActiveFrame, type Frame } from "./frame.js"; -import type { Subscriptions } from "./subscriptions.js"; -import type { Timeline } from "./timeline.js"; - -export class FrameStack { - #current: ActiveFrame | null; - #subscriptions: Subscriptions; - #timeline: Timeline; - - static didConsumeCell(frames: FrameStack, tag: CellTag, caller: Stack): void { - frames.#debug.consumeCell(tag, caller); - frames.#didConsumeReactive(tag, caller); - } - - static didConsumeFrame( - frames: FrameStack, - frame: interfaces.FormulaTag, - diff: interfaces.Diff, - caller: Stack - ): void { - frames.#debug.consumeFrame(frame, diff, caller); - frames.#didConsumeReactive(frame, caller); - } - - static empty(timeline: Timeline, subscriptions: Subscriptions): FrameStack { - return new FrameStack(subscriptions, null, timeline); - } - - constructor( - subscriptions: Subscriptions, - current: ActiveFrame | null, - timeline: Timeline - ) { - this.#subscriptions = subscriptions; - this.#current = current; - this.#timeline = timeline; - } - - get currentFrame(): ActiveFrame | null { - return this.#current; - } - - get #debug(): DebugTimeline { - return this.#timeline.log; - } - - /** - * Evaluate a block of code, returning a new Frame. - */ - evaluate( - block: () => T, - { - description, - }: { - description: interfaces.Description; - } - ): Frame { - const frame = this.#start(description) as ActiveFrame; - - try { - const result = block(); - return this.#end(frame, result); - } catch (e) { - this.finally(frame); - throw e; - } - } - - /** - * Open a new frame, returning an `ActiveFrame`. - * - * Any consumptions between a call to `open()` and the call to - * {@linkcode ActiveFrame.prototype.finalize ActiveFrame#finalize} are assigned to this frame. - */ - open({ - description, - }: { - description: interfaces.Description; - }): ActiveFrame { - return this.#start(description) as ActiveFrame; - } - - #didConsumeReactive(tag: interfaces.Tag, caller: Stack): void { - const frame = this.currentFrame; - if (frame) { - frame.add(tag); - return; - } else { - const delegatesTo = [...tag.subscriptionTargets()]; - - for (const target of delegatesTo) { - if (target.type === "cell") { - this.#timeline.untrackedRead(target, caller); - } - } - } - } - - #end(active: ActiveFrame, value: T): Frame { - const { prev, frame } = active.finalize(value, this.#timeline); - this.#current = prev; - return frame; - } - - finally(prev: ActiveFrame | null): void { - this.#current = prev; - } - - /** @internal */ - start(frame: Frame): ActiveFrame { - return this.#start(frame.description, frame) as ActiveFrame; - } - - /** @internal */ - willEvaluate(): void { - this.#timeline.willEvaluate(); - } - - /** @internal */ - end(frame: ActiveFrame, value: T): Frame { - return this.#end(frame, value); - } - - /** @internal */ - updateSubscriptions(frame: Frame): void { - this.#subscriptions.update(getTag(frame)); - } - - #start( - description: interfaces.Description, - frame?: Frame - ): ActiveFrame { - const prev = this.#current; - return (this.#current = ActiveFrame.create( - frame ?? null, - prev, - description - )); - } - - update(frame: Frame): ActiveFrame { - return this.#start(frame.description, frame) as ActiveFrame; - } -} diff --git a/packages/universal/runtime/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts index 9fdc5ef3..96f74df3 100644 --- a/packages/universal/runtime/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -1,4 +1,10 @@ -import type { CellTag, Diff, FormulaTag, Tag } from "@starbeam/interfaces"; +import type { + CellTag, + Diff, + FormulaTag, + SubscriptionTarget, + Tag, +} from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { diff } from "./utils.js"; @@ -42,8 +48,9 @@ export class Subscriptions { return new Subscriptions(); } - readonly #formulaMap = SubscriberMap.empty(); + readonly #subscriberMap = SubscriberMap.empty(); readonly #cellMap = CellMap.empty(); + readonly #tdzSubscriptionMap = new WeakMap>(); /** * Register a notification for a reactive value. @@ -69,16 +76,11 @@ export class Subscriptions { * different dependencies. */ register(target: Tag, ready: NotifyReady): Unsubscribe { - const subscriptionTargets = target.subscriptionTargets(); + const subscriptionTargets = target.subscriptionTargets; - const unsubscribes = [...subscriptionTargets].map((t) => { - const entry = this.#formulaMap.register(t); - for (const dependency of t.dependencies()) { - this.#cellMap.register(dependency, entry); - } - - return entry.subscribe(ready); - }); + const unsubscribes = subscriptionTargets.map((t) => + this.#register(t, ready) + ); return () => { for (const unsubscribe of unsubscribes) { @@ -87,6 +89,38 @@ export class Subscriptions { }; } + #register(target: SubscriptionTarget, ready: NotifyReady): Unsubscribe { + if (target.type === "formula" && !target.initialized) { + const set = this.#upsertTdzSubscriptions(target, ready); + + // FIXME: Support removal after upgrade + return () => { + set.delete(ready); + }; + } else { + const entry = this.#subscriberMap.register(target); + for (const dependency of target.dependencies()) { + this.#cellMap.register(dependency, entry); + } + return entry.subscribe(ready); + } + } + + #upsertTdzSubscriptions( + formula: FormulaTag, + ready: NotifyReady + ): Set { + let tdzSubscriptions = this.#tdzSubscriptionMap.get(formula); + + if (!tdzSubscriptions) { + tdzSubscriptions = new Set(); + this.#tdzSubscriptionMap.set(formula, tdzSubscriptions); + } + + tdzSubscriptions.add(ready); + return tdzSubscriptions; + } + /** * Notify the subscribers of a particular cell. This happens synchronously during mutation. */ @@ -99,10 +133,19 @@ export class Subscriptions { * results in removing mappings from cells that are no longer dependencies and adding mappings for * cells that have become dependencies. */ - update(frame: FormulaTag): void { + update(formula: FormulaTag): void { + const tdzSubscriptions = this.#tdzSubscriptionMap.get(formula); + + if (tdzSubscriptions) { + for (const ready of tdzSubscriptions) { + this.#register(formula, ready); + } + this.#tdzSubscriptionMap.delete(formula); + } + const cellMap = this.#cellMap; - const { add, remove, entry } = this.#formulaMap.update(frame); + const { add, remove, entry } = this.#subscriberMap.update(formula); cellMap.remove(remove, entry); cellMap.add(add, entry); } diff --git a/packages/universal/runtime/src/timeline/timeline.ts b/packages/universal/runtime/src/timeline/timeline.ts deleted file mode 100644 index 1fa32038..00000000 --- a/packages/universal/runtime/src/timeline/timeline.ts +++ /dev/null @@ -1,191 +0,0 @@ -import type { Stack } from "@starbeam/debug"; -import { DebugTimeline } from "@starbeam/debug"; -import type * as interfaces from "@starbeam/interfaces"; -import type { CellTag, Tagged } from "@starbeam/interfaces"; -import { getNow, getTag, NOW } from "@starbeam/tags"; - -import type { Unsubscribe } from "../lifetime/object-lifetime.js"; -import { FrameStack } from "./frames.js"; -import { type NotifyReady, Subscriptions } from "./subscriptions.js"; - -type TimelineOp = "consumed" | "bumped" | "evaluating" | "initial"; - -/** - * # How Subscriptions Work at the Lowest Level - * - * You subscribe to an object implementing ReactiveProtocol by using `Timeline#on.change`. - * - * ## Composites - * - * If the object represents a composite, the {@linkcode Timeline} will immediately subscribe to the - * dependencies of the composite. - * - * Whenever any of those dependencies change, the timeline will notify the subscriber. Whenever a - * reactive object's composite dependencies may have changed (i.e. when it was polled), the object - * is responsible for calling `TIMELINE.update(object)` to notify the timeline. This updates the - * internal dependencies of that object used for notifications. - * - * ## Delegates - * - * If an object implementing {@linkcode ReactiveCore} simply polls another reactive object, it - * can use a {@linkcode DelegateInternals} property to point to that object. In this case, the - * object doesn't need to worry about `TIMELINE.update`. - * - * ## Notifications - * - * Whenever a {@linkcode MutableInternals} is updated, the timeline will notify all subscribers of - * reactives that depend on that dependency. - */ -export class Timeline implements interfaces.DeprecatedTimeline { - #debugTimeline: DebugTimeline | null = null; - readonly #frame: FrameStack; - - on = { - change: (target: Tagged, ready: NotifyReady): Unsubscribe => { - return this.#subscriptions.register(getTag(target), ready); - }, - } as const; - - /** - * Dynamic assertions that are used in development mode to detect reads that occur outside of a - * tracking frame, but which are used to produce rendered outputs. - */ - #readAssertions = new Set< - (reactive: interfaces.Tag, caller: Stack) => void - >(); - - readonly #subscriptions: Subscriptions; - #lastOp: TimelineOp; - - /** - * In debug mode, register a barrier for untracked reads. This allows you to throw an error if an - * untracked read occurred in a context (such as a render function) that a renderer knows will - * produce rendered content. - */ - declare untrackedReadBarrier: ( - assertion: (reactive: interfaces.Tag, caller: Stack) => void - ) => void; - - static create(): Timeline { - return new Timeline(Subscriptions.create(), "initial"); - } - - private constructor(subscriptions: Subscriptions, lastOp: TimelineOp) { - this.#subscriptions = subscriptions; - this.#frame = FrameStack.empty(this, subscriptions); - this.#lastOp = lastOp; - - if (import.meta.env.DEV) { - this.untrackedReadBarrier = ( - assertion: (reactive: interfaces.Tag, caller: Stack) => void - ): void => { - this.#readAssertions.add(assertion); - }; - } - } - - get #debug(): DebugTimeline { - if (!this.#debugTimeline) { - this.#debugTimeline = DebugTimeline.create({ now: getNow }, { getTag }); - } - - return this.#debugTimeline; - } - - get frame(): FrameStack { - return this.#frame; - } - - get log(): DebugTimeline { - return this.#debug; - } - - // Returns the current timestamp - get now(): interfaces.Timestamp { - return NOW.now; - } - - #adjustTimestamp( - operation: "consumed" | "bumped" | "evaluating" - ): interfaces.Timestamp { - const prev = this.#lastOp; - const prevIsRead = prev === "consumed" || prev === "evaluating"; - const nextIsRead = operation === "consumed" || operation === "evaluating"; - - this.#lastOp = operation; - if (prevIsRead === nextIsRead) { - return this.now; - } else { - return this.next(); - } - } - - bumpCell(mutable: interfaces.CellTag, caller: Stack): interfaces.Timestamp { - return this.bump(mutable, caller); - } - - didConsumeCell(cell: interfaces.CellTag, caller: Stack): void { - this.#adjustTimestamp("consumed"); - FrameStack.didConsumeCell(this.#frame, cell, caller); - } - - bump(mutable: interfaces.CellTag, caller: Stack): interfaces.Timestamp { - const now = this.#adjustTimestamp("bumped"); - - if (import.meta.env.DEV) { - this.#debug.updateCell(mutable, caller); - } - - this.#subscriptions.notify(mutable); - return now; - } - - didConsumeFrame( - frame: interfaces.Frame, - diff: interfaces.Diff, - caller: Stack - ): void { - this.#adjustTimestamp("consumed"); - FrameStack.didConsumeFrame(this.#frame, getTag(frame), diff, caller); - } - - next(): interfaces.Timestamp { - return NOW.bump(); - } - - /** - * When a reactive's dependencies might have changed, any renderables that depend on this reactive - * need to refresh their dependencies. If there are no renderers for this reactive value, - * {@linkcode update} does nothing. - * - * Otherwise, each relevant renderable will unsubscribe from any stale dependencies and subscribe - * to any new dependencies. - * - * For example, Formulas call this method after recomputing their value, which results in a - * possible change to their dependencies. - */ - update(reactive: interfaces.Tagged): void { - this.#subscriptions.update(getTag(reactive)); - } - - willEvaluate(): void { - this.#lastOp = "evaluating"; - } - - mutation(description: string, callback: () => T): T { - if (import.meta.env.DEV) { - return this.#debug.mutation(description, callback); - } - - return callback(); - } - - /// DEBUG MODE /// - - /** @internal */ - untrackedRead(cell: CellTag, caller: Stack): void { - for (const assertion of this.#readAssertions) { - assertion(cell, caller); - } - } -} diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index 41106a0b..0825e0dc 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -16,11 +16,7 @@ enum Phase { write = "write", } -export class ReactiveError extends Error { - constructor(message: string) { - super(message); - } -} +export class ReactiveError extends Error {} /** * The Timeline is the core of the runtime. @@ -34,21 +30,16 @@ class Mutations implements SubscriptionRuntime { readonly #lastPhase: Phase = Phase.read; subscribe(target: Tag, ready: NotifyReady): Unsubscribe { - if (target.tdz) { - throw new ReactiveError( - `The tag ${target.description.describe({ - color: false, - })} isn't initialized yet, so you can't subscribe to it. This is a bug in the implementation of a primitive or renderer.` - ); - } - return this.#subscriptions.register(target, ready); } - bump(cell: CellTag): Timestamp { - const next = this.#updatePhase(Phase.write); - this.#subscriptions.notify(cell); - return next; + bump(cell: CellTag): { revision: Timestamp; notify: () => void } { + return { + revision: this.#updatePhase(Phase.write), + notify: () => { + this.#subscriptions.notify(cell); + }, + }; } update(formula: FormulaTag): void { @@ -68,8 +59,17 @@ export const SUBSCRIPTION_RUNTIME = new Mutations(); export class PublicTimeline { readonly on = { - change: (target: Tagged, ready: NotifyReady): Unsubscribe => { - return SUBSCRIPTION_RUNTIME.subscribe(getTag(target), ready); + change: (tagged: Tagged, ready: NotifyReady): Unsubscribe => { + const unsubscribes = new Set(); + for (const target of getTag(tagged).subscriptionTargets) { + unsubscribes.add(SUBSCRIPTION_RUNTIME.subscribe(target, ready)); + } + + return () => { + for (const unsubscribe of unsubscribes) { + unsubscribe(); + } + }; }, }; diff --git a/packages/universal/runtime/tests/consume.spec.ts b/packages/universal/runtime/tests/consume.spec.ts index b1474439..0f12aa55 100644 --- a/packages/universal/runtime/tests/consume.spec.ts +++ b/packages/universal/runtime/tests/consume.spec.ts @@ -33,7 +33,7 @@ describe("consumption", () => { const tag = FormulaTag.create(Desc("formula"), () => tags); // unset the tag's TDZ, which will allow subscriptions to the tag. Normally // this happens in the implementation of `Formula`, once the value was computed. - tag.unsetTdz(); + tag.markInitialized(); const stale = new Staleness(); RUNTIME.subscriptions.subscribe(tag, () => { diff --git a/packages/universal/runtime/tests/subscribing.spec.ts b/packages/universal/runtime/tests/subscribing.spec.ts index 96b6d936..d3f81062 100644 --- a/packages/universal/runtime/tests/subscribing.spec.ts +++ b/packages/universal/runtime/tests/subscribing.spec.ts @@ -1,8 +1,8 @@ import { isPresentArray } from "@starbeam/core-utils"; import { Desc, logTag } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; -import { CachedFormula,Cell } from "@starbeam/reactive"; -import { PUBLIC_TIMELINE, ReactiveError, TAG } from "@starbeam/runtime"; +import { CachedFormula, Cell } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; import { DelegateTag, getTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; @@ -25,13 +25,21 @@ describe("Tagged", () => { expect(cell.current).toBe(1); }); - test("subscribing to a formula before reading it is an error", () => { + test("subscribing to a formula before reading it lazily subscribes once read", () => { const cell = Cell(0); const formula = CachedFormula(() => cell.current); + let stale = false; + + PUBLIC_TIMELINE.on.change(formula, () => { + stale = true; + }); + + expect(formula.current).toBe(0); + expect(stale).toBe(false); - expect(() => PUBLIC_TIMELINE.on.change(formula, () => void 0)).toThrow( - ReactiveError - ); + cell.current++; + expect(formula.current).toBe(1); + expect(stale).toBe(true); }); test("subscribing to a formula", () => { @@ -90,7 +98,7 @@ describe("Tagged", () => { expect(cell.current).toBe(1); }); - test("subscribing to a formula before reading one of its formula targets is an error", () => { + test("subscribing to a delegate before reading one of its formula targets lazily subscribes once read", () => { const cell = Cell(0); const formula = CachedFormula(() => cell.current); @@ -101,9 +109,19 @@ describe("Tagged", () => { ]), }; - expect(() => PUBLIC_TIMELINE.on.change(delegate, () => void 0)).toThrow( - ReactiveError - ); + let stale = false; + + PUBLIC_TIMELINE.on.change(delegate, () => { + stale = true; + }); + + expect(formula.current).toBe(0); + expect(stale).toBe(false); + + cell.current++; + expect(formula.current).toBe(1); + + expect(stale).toBe(true); }); test("subscribing to a formula delegate", () => { diff --git a/packages/universal/runtime/tests/subscription.spec.ts b/packages/universal/runtime/tests/subscription.spec.ts index 3b89cbdb..d1baa21c 100644 --- a/packages/universal/runtime/tests/subscription.spec.ts +++ b/packages/universal/runtime/tests/subscription.spec.ts @@ -1,16 +1,25 @@ import { CachedFormula, Cell } from "@starbeam/reactive"; -import { PUBLIC_TIMELINE, ReactiveError } from "@starbeam/runtime"; +import { PUBLIC_TIMELINE } from "@starbeam/runtime"; import { describe, expect, test } from "vitest"; -describe("frames", () => { +describe("formula subscription", () => { test("subscription before first consumption", () => { const cell = Cell("Tom Dale"); const formula = CachedFormula(() => cell.current); - expect(() => PUBLIC_TIMELINE.on.change(formula, () => void 0)).toThrow( - ReactiveError - ); + let stale = false; + PUBLIC_TIMELINE.on.change(formula, () => { + stale = true; + }); + + expect(stale).toBe(false); + expect(formula.current).toBe("Tom Dale"); + expect(stale).toBe(false); + + cell.current = "Jerry Seinfeld"; + expect(stale).toBe(true); + expect(formula.current).toBe("Jerry Seinfeld"); }); test("subscription after first consumption", () => { diff --git a/packages/universal/service/src/service.ts b/packages/universal/service/src/service.ts index b6338547..a48b7e76 100644 --- a/packages/universal/service/src/service.ts +++ b/packages/universal/service/src/service.ts @@ -1,9 +1,10 @@ import { Desc } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; +import type { IntoResourceBlueprint } from "@starbeam/resource"; import { Resource, type ResourceBlueprint, use } from "@starbeam/resource"; import { CONTEXT } from "@starbeam/runtime"; -type Blueprint = ResourceBlueprint; +type Blueprint = IntoResourceBlueprint; export function Service( blueprint: Blueprint, diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index eb766bb2..fc6ddd46 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -35,7 +35,8 @@ export abstract class Tag } abstract readonly type: interfaces.TagType; - abstract readonly tdz: boolean; + abstract readonly initialized: boolean; + abstract readonly subscriptionTargets: readonly interfaces.SubscriptionTarget[]; readonly #description: Description; constructor(description: Description) { @@ -64,14 +65,6 @@ export abstract class Tag get description(): Description { return this.#description; } - - /** - * By default, a tag yields itself when asked for subsbcription target. The - * delegate tag overrides this behavior. - */ - *subscriptionTargets(): interfaces.List { - yield this as interfaces.Tag; - } } export class CellTag extends Tag implements interfaces.CellTag { @@ -80,7 +73,7 @@ export class CellTag extends Tag implements interfaces.CellTag { } readonly type = "cell"; - readonly tdz = false; + readonly initialized = true; #frozen = false; #lastUpdated: Timestamp; @@ -113,6 +106,10 @@ export class CellTag extends Tag implements interfaces.CellTag { this.#lastUpdated = timestamp; } + get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { + return [this as interfaces.SubscriptionTarget]; + } + override dependencies(): interfaces.CellTag[] { return this.#frozen ? [] : [this]; } @@ -122,7 +119,9 @@ export class CellTag extends Tag implements interfaces.CellTag { throw TypeError("Cannot update frozen object"); } - this.#lastUpdated = runtime.subscriptions.bump(this); + const { notify, revision } = runtime.subscriptions.bump(this); + this.#lastUpdated = revision; + notify(); } } @@ -132,10 +131,14 @@ export class StaticTag extends Tag implements interfaces.StaticTag { } readonly type = "static"; - readonly tdz = false; + readonly initialized = true; override readonly lastUpdated = NOW.now; + get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { + return []; + } + override dependencies(): readonly interfaces.CellTag[] { return []; } @@ -146,37 +149,37 @@ export class FormulaTag extends Tag implements interfaces.FormulaTag { description: Description, children: () => interfaces.List ): FormulaTag { - return new FormulaTag(description, children, true); + return new FormulaTag(description, children, false); } readonly type = "formula"; readonly #children: () => interfaces.List; - #tdz: boolean; + #initialized: boolean; private constructor( description: Description, children: () => interfaces.List, - tdz: boolean + initialized: boolean ) { super(description); this.#children = children; - this.#tdz = tdz; + this.#initialized = initialized; } [INSPECT]() { return DisplayStruct("Formula", { id: this.description.id, - initialized: !this.#tdz, + initialized: this.#initialized, children: [...this.#children()], }); } - get tdz(): boolean { - return this.#tdz; + get initialized(): boolean { + return this.#initialized; } - unsetTdz(): void { - this.#tdz = false; + markInitialized(): void { + this.#initialized = true; } children(): readonly interfaces.Tag[] { @@ -198,6 +201,10 @@ export class FormulaTag extends Tag implements interfaces.FormulaTag { override dependencies(): interfaces.CellTag[] { return this.children().flatMap((child) => child.dependencies()); } + + get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { + return [this]; + } } export class DelegateTag extends Tag implements interfaces.DelegateTag { @@ -210,6 +217,7 @@ export class DelegateTag extends Tag implements interfaces.DelegateTag { readonly type = "delegate"; readonly #targets: readonly interfaces.Tag[]; + readonly #subscriptionTargets: readonly interfaces.SubscriptionTarget[]; private constructor( description: Description, @@ -217,20 +225,21 @@ export class DelegateTag extends Tag implements interfaces.DelegateTag { ) { super(description); this.#targets = targets; + this.#subscriptionTargets = targets.flatMap( + (target) => target.subscriptionTargets + ); } - get tdz(): boolean { - return this.#targets.some((target) => target.tdz); + get initialized(): boolean { + return this.#targets.every((target) => target.initialized); } get targets(): readonly interfaces.Tag[] { return this.#targets; } - override *subscriptionTargets(): interfaces.List { - for (const target of this.#targets) { - yield* target.subscriptionTargets(); - } + get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { + return this.#subscriptionTargets; } override dependencies(): readonly interfaces.CellTag[] { @@ -238,6 +247,6 @@ export class DelegateTag extends Tag implements interfaces.DelegateTag { } override get lastUpdated(): Timestamp { - return Tag.lastUpdatedIn(this.subscriptionTargets()); + return Tag.lastUpdatedIn(this.subscriptionTargets); } } diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 32ea1581..2800f60a 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -5,11 +5,6 @@ export { CustomBuilder, } from "./src/reactive-core/custom.js"; export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; -export { - Factory, - type IntoReactiveObject, - type IntoResource, -} from "./src/reactive-core/into.js"; export type { Blueprint, IntoReactive, diff --git a/packages/universal/universal/src/reactive-core/into.ts b/packages/universal/universal/src/reactive-core/into.ts deleted file mode 100644 index bb207105..00000000 --- a/packages/universal/universal/src/reactive-core/into.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { Description } from "@starbeam/debug"; -import { Desc } from "@starbeam/debug"; -import { intoReactive, isReactive } from "@starbeam/reactive"; -import { Resource, type ResourceBlueprint } from "@starbeam/resource"; - -import type { ReactiveBlueprint } from "./reactive.js"; -import { type Blueprint, Reactive, type ReactiveFactory } from "./reactive.js"; - -export type IntoResource = ResourceBlueprint | ReactiveBlueprint; - -export type IntoResourceType> = - I extends ResourceBlueprint - ? ResourceBlueprint - : I extends ReactiveBlueprint | ReactiveFactory - ? ReactiveBlueprint - : never; - -export function IntoResource>( - create: I, - description: Description -): IntoResourceType { - return typeof create === "function" - ? (Resource(create, description) as IntoResourceType) - : (create as unknown as IntoResourceType); -} - -export type Factory = Blueprint | ReactiveFactory; - - -export const Factory = { - create: createReactiveObject, - initial, - resource, -}; - -function initial(create: IntoResource): T | undefined { - if (create instanceof ResourceBlueprint) { - return ResourceBlueprint.initial(create); - } else { - return undefined; - } -} - -function resource( - create: IntoResource, - owner: object, - description?: Description | string -): Reactive { - const desc = Desc("resource", description); - return intoReactive(IntoResource(create, desc).create(owner)) as Reactive; -} - -export type IntoReactiveObject = ReactiveBlueprint | ReactiveFactory; - -function createReactiveObject>( - create: IntoReactiveObject | R -): U | R; -function createReactiveObject(create: IntoReactiveObject): T; -function createReactiveObject>(create: T): T; -function createReactiveObject( - create: IntoReactiveObject | Reactive -): unknown { - if (isReactive(create)) { - return create; - } else { - return IntoReactiveObject(create).create(); - } -} - -function IntoReactiveObject( - create: ReactiveBlueprint | ReactiveFactory -): ReactiveBlueprint { - return typeof create === "function" ? Reactive(create) : create; -} diff --git a/packages/universal/universal/tests/factory.spec.todo.ts b/packages/universal/universal/tests/factory.spec.todo.ts deleted file mode 100644 index 28345d63..00000000 --- a/packages/universal/universal/tests/factory.spec.todo.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { entryPointFn } from "@starbeam/debug"; -import { Static } from "@starbeam/reactive"; -import { Frame } from "@starbeam/runtime"; -import { describeTagged } from "@starbeam/tags"; -import { Cell, Reactive } from "@starbeam/universal"; -import { describe, expect, test } from "@starbeam-workspace/test-utils"; - -describe("reactive Factory", () => { - describe.each([0, 1, 0n, "hello", "", true, false, null, undefined])( - "representing a primitive value: %s", - (value) => { - test(`Reactive(() => ${s( - value - )}) returns a reactive that returns the same value`, () => { - const reactive = Reactive(() => value); - expect(reactive.create()).toBe(value); - }); - - test(`Reactive(() => Static(${s( - value - )})) returns a reactive that returns the same value`, () => { - const reactive = Reactive(() => Static(value)); - expect(reactive.create().current).toBe(value); - }); - - test(`Reactive(() => Reactive(() => ${s(value)})))`, () => { - const reactive = Reactive(() => Reactive(() => value)); - expect(reactive.create()).toBe(value); - }); - } - ); - - describe("returning a single mutable cell", () => { - let i = 0; - const Counter = Reactive(() => Cell(0, { description: `Counter ${i++}` })); - - test("the inner cell is returned", () => { - const counter = Counter.create(); - - if (!import.meta.env.PROD) { - expect(describeTagged(counter)).toBe("Counter 0"); - } - - expect(counter.current).toBe(0); - counter.update((value) => value + 1); - expect(counter.current).toBe(1); - }); - - test("the returned value invalidates when the cell changes", () => { - const counter = Counter.create(); - - const context = TrackingContext(() => counter.current); - - expectStale(context, 0); - counter.update((value) => value + 1); - expectStale(context, 1); - }); - }); - - describe("an abstraction over mutable cells", () => { - const Counter = Reactive(() => { - const cell = Cell(0); - const extra = Cell(0); - - return { - get count() { - return cell.current; - }, - get extra() { - return extra.current; - }, - increment() { - cell.update((value) => value + 1); - }, - incrementExtra() { - extra.update((value) => value + 1); - }, - }; - }); - - test("the cell is created", () => { - const counter = Counter.create(); - expect(counter.count).toBe(0); - counter.increment(); - expect(counter.count).toBe(1); - }); - - test("the reactive object *granularly* invalidates when its dependencies change", () => { - const counter = Counter.create(); - const countContext = TrackingContext(() => counter.count); - const extraContext = TrackingContext(() => counter.extra); - - expectStale(countContext, 0); - expectStale(extraContext, 0); - - counter.increment(); - - expectStale(countContext, 1); - expectValid(extraContext, 0); - - counter.incrementExtra(); - - expectValid(countContext, 1); - expectStale(extraContext, 1); - - expectValid(countContext, 1); - expectValid(extraContext, 1); - - counter.increment(); - counter.incrementExtra(); - - expectStale(countContext, 2); - expectStale(extraContext, 2); - }); - }); - - describe("a class", () => { - class Counter { - #cell = Cell(0); - #extra = Cell(0); - - get count(): number { - return this.#cell.current; - } - - get extra(): number { - return this.#extra.current; - } - - increment(): void { - this.#cell.update((value) => value + 1); - } - - incrementExtra(): void { - this.#extra.update((value) => value + 1); - } - } - - test("the cell is created", () => { - const counter = Reactive(Counter).create(); - expect(counter.count).toBe(0); - counter.increment(); - expect(counter.count).toBe(1); - }); - - test("the reactive object *granularly* invalidates when its dependencies change", () => { - const counter = Reactive(Counter).create(); - const countContext = TrackingContext(() => counter.count); - const extraContext = TrackingContext(() => counter.extra); - - expectStale(countContext, 0); - expectStale(extraContext, 0); - - counter.increment(); - - expectStale(countContext, 1); - expectValid(extraContext, 0); - - counter.incrementExtra(); - - expectValid(countContext, 1); - expectStale(extraContext, 1); - - expectValid(countContext, 1); - expectValid(extraContext, 1); - - counter.increment(); - counter.incrementExtra(); - - expectStale(countContext, 2); - expectStale(extraContext, 2); - }); - }); -}); - -type Primitive = number | bigint | string | boolean | null | undefined | symbol; - -function s(value: Primitive): string { - switch (typeof value) { - case "bigint": - return `${value}n`; - case "symbol": - return `Symbol(${value.description ?? ""})`; - default: - return JSON.stringify(value); - } -} - -type Validation = - | { status: "valid"; value: T } - | { status: "stale"; value: T }; - -function valid(value: T): Validation { - return { status: "valid", value }; -} - -function stale(value: T): Validation { - return { status: "stale", value }; -} - -const expectStale = entryPointFn((context: Context, value: T) => { - expect(context.value).toEqual(stale(value)); - expect(context.value, "the value after validating").toEqual(valid(value)); -}); - -const expectValid = entryPointFn((context: Context, value: T) => { - expect(context.value).toEqual(valid(value)); -}); - -interface Context { - readonly value: Validation; -} - -// function TrackingContext(callback: () => T): Context { -// const formula = FormulaValidation(callback); - -// return { -// get value(): Validation { -// const status = formula.frame.validate(); - -// if (status.status === "valid") { -// return status; -// } else { -// return { -// status: "stale", -// value: Frame.value(formula.poll()), -// }; -// } -// }, -// }; -// } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 981e0dec..415450d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -758,9 +758,15 @@ importers: '@starbeam/reactive': specifier: workspace:^ version: link:../../universal/reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../../universal/resource '@starbeam/runtime': specifier: workspace:^ version: link:../../universal/runtime + '@starbeam/service': + specifier: workspace:^ + version: link:../../universal/service '@starbeam/shared': specifier: workspace:^ version: link:../../universal/shared From fb52ba81b88772053a1f464d2085aae0949e0676 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Tue, 4 Apr 2023 16:47:42 -0700 Subject: [PATCH 26/46] Preact tests pass! --- packages/preact/preact/index.ts | 2 +- packages/preact/preact/package.json | 2 + packages/preact/preact/src/create.ts | 2 +- packages/preact/preact/src/frame.ts | 46 ++++++++++--------- packages/preact/preact/src/resource.ts | 24 ++++++---- packages/preact/preact/tests/package.json | 2 + packages/preact/preact/tests/services.spec.ts | 11 +++-- packages/universal/interfaces/index.d.ts | 2 + packages/universal/reactive/index.ts | 7 ++- .../src/primitives/formula-lifecycle.ts | 3 +- packages/universal/reactive/src/utils.ts | 11 +++-- .../universal/runtime/src/timeline/tracker.ts | 6 ++- pnpm-lock.yaml | 12 +++++ 13 files changed, 86 insertions(+), 44 deletions(-) diff --git a/packages/preact/preact/index.ts b/packages/preact/preact/index.ts index d8ebe412..c592a33d 100644 --- a/packages/preact/preact/index.ts +++ b/packages/preact/preact/index.ts @@ -1,3 +1,3 @@ export { create, createCell } from "./src/create.js"; export { setup } from "./src/options.js"; -export { use } from "./src/resource.js"; +export { service, use } from "./src/resource.js"; diff --git a/packages/preact/preact/package.json b/packages/preact/preact/package.json index 3056657c..d23491db 100644 --- a/packages/preact/preact/package.json +++ b/packages/preact/preact/package.json @@ -36,7 +36,9 @@ "@starbeam/interfaces": "workspace:^", "@starbeam/preact-utils": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", + "@starbeam/service": "workspace:^", "@starbeam/tags": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" diff --git a/packages/preact/preact/src/create.ts b/packages/preact/preact/src/create.ts index 58677ef7..1658086e 100644 --- a/packages/preact/preact/src/create.ts +++ b/packages/preact/preact/src/create.ts @@ -1,4 +1,4 @@ -import { type Description, Desc } from "@starbeam/debug"; +import { Desc, type Description } from "@starbeam/debug"; import { Cell } from "@starbeam/universal"; import { useMemo } from "preact/hooks"; diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index 5c26bdba..8c20fcc0 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -1,20 +1,16 @@ import { getLast } from "@starbeam/core-utils"; -import type { Description } from "@starbeam/debug"; -import type { Tag } from "@starbeam/interfaces"; +import { Desc, type Description } from "@starbeam/debug"; import type { InternalComponent } from "@starbeam/preact-utils"; -import { - type Frame, - PUBLIC_TIMELINE, - RUNTIME, - type Unsubscribe, -} from "@starbeam/runtime"; +import type { FinalizedFormula, InitializingFormula } from "@starbeam/reactive"; +import { FormulaLifecycle } from "@starbeam/reactive"; +import { PUBLIC_TIMELINE, RUNTIME, type Unsubscribe } from "@starbeam/runtime"; +import { FormulaTag } from "@starbeam/tags"; import { expected, isPresent, verify } from "@starbeam/verify"; -type ActiveFrame = (() => Set) | null; - export class ComponentFrame { - #active: ActiveFrame; - #frame: Frame | null; + #active: InitializingFormula | null; + #frame: FinalizedFormula | null; + #tag: FormulaTag; #subscription: Unsubscribe | null; static #frames = new WeakMap(); @@ -48,7 +44,10 @@ export class ComponentFrame { return current; } - static end(component: InternalComponent, subscription?: () => void): Frame { + static end( + component: InternalComponent, + subscription?: () => void + ): FinalizedFormula { const frame = ComponentFrame.#frames.get(component); verify( @@ -71,39 +70,42 @@ export class ComponentFrame { } private constructor( - frame: Frame | null, - active: ActiveFrame, + frame: FinalizedFormula | null, + active: InitializingFormula | null, subscribed: Unsubscribe | null ) { this.#frame = frame; this.#active = active; + this.#tag = FormulaTag.create( + Desc("external", "preact:component"), + () => this.#frame?.children() ?? [] + ); this.#subscription = subscribed; } #start(description: Description): void { if (this.#frame) { - this.#active = RUNTIME.autotracking.start(); + this.#active = this.#frame.update(); // this.#active = TIMELINE.frame.update(this.#frame); } else { - this.#active = TIMELINE.frame.open({ - description, - }); + this.#active = FormulaLifecycle({ description }); } } - #end(subscription: (() => void) | undefined): Frame { + #end(subscription: (() => void) | undefined) { verify( this.#active, isPresent, expected.when("in preact's _diff hook").as("an active tracking frame") ); - const frame = (this.#frame = this.#active.finalize(null, TIMELINE).frame); + const frame = (this.#frame = this.#active.done()); + RUNTIME.subscriptions.update(this.#tag); this.#active = null; if (subscription) { - this.#subscription = PUBLIC_TIMELINE.on.change(frame, subscription); + this.#subscription = PUBLIC_TIMELINE.on.change(this.#tag, subscription); } return frame; diff --git a/packages/preact/preact/src/resource.ts b/packages/preact/preact/src/resource.ts index 3073bef4..7b8d87d4 100644 --- a/packages/preact/preact/src/resource.ts +++ b/packages/preact/preact/src/resource.ts @@ -1,17 +1,25 @@ -import type { ResourceBlueprint } from "@starbeam/universal"; -import { Factory } from "@starbeam/universal"; +import type { ReadValue } from "@starbeam/reactive"; +import type { IntoResourceBlueprint } from "@starbeam/resource"; +import * as resource from "@starbeam/resource"; +import { service as createService } from "@starbeam/service"; import { isPresent, verified } from "@starbeam/verify"; import { useMemo } from "preact/hooks"; import { getCurrentComponent } from "./options.js"; -export function use( - blueprint: - | ResourceBlueprint - | (() => ResourceBlueprint) -): T { +export function use( + blueprint: IntoResourceBlueprint +): ReadValue { return useMemo(() => { const owner = verified(getCurrentComponent(), isPresent); - return Factory.resource(blueprint, owner); + return resource.use(blueprint, { lifetime: owner }); + }, []).current; +} + +export function service( + blueprint: IntoResourceBlueprint +): ReadValue { + return useMemo(() => { + return createService(blueprint); }, []).current; } diff --git a/packages/preact/preact/tests/package.json b/packages/preact/preact/tests/package.json index 742b5c7e..2296896d 100644 --- a/packages/preact/preact/tests/package.json +++ b/packages/preact/preact/tests/package.json @@ -11,7 +11,9 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/preact": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", + "@starbeam/service": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam-workspace/preact-testing-utils": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", diff --git a/packages/preact/preact/tests/services.spec.ts b/packages/preact/preact/tests/services.spec.ts index effa47e2..7099b770 100644 --- a/packages/preact/preact/tests/services.spec.ts +++ b/packages/preact/preact/tests/services.spec.ts @@ -1,10 +1,11 @@ // @vitest-environment jsdom -import { setup } from "@starbeam/preact"; -import { service } from "@starbeam/universal"; +import { service, setup } from "@starbeam/preact"; +import type { Resource } from "@starbeam/resource"; +import { getTag } from "@starbeam/tags"; import { - type HtmlNode, html, + type HtmlNode, rendering, } from "@starbeam-workspace/preact-testing-utils"; import { @@ -67,3 +68,7 @@ describe("services", () => { }) ); }); + +function id(service: Resource): string { + return JSON.stringify(getTag(service).id); +} diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts index 4d0ae996..355631b7 100644 --- a/packages/universal/interfaces/index.d.ts +++ b/packages/universal/interfaces/index.d.ts @@ -58,7 +58,9 @@ export type { UpdateOptions, } from "./src/runtime.js"; export type { + Stack as CallStack, DisplayParts, + /** @deprecated use {@linkcode CallStack} */ Stack, StackFrame, StackFrameDisplayOptions, diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 5da68aea..31450b6f 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -2,7 +2,11 @@ export { CachedFormula } from "./src/primitives/cached.js"; export type { CellOptions, Equality } from "./src/primitives/cell.js"; export { Cell } from "./src/primitives/cell.js"; export { Formula } from "./src/primitives/formula.js"; -export { FormulaLifecycle } from "./src/primitives/formula-lifecycle.js"; +export { + type FinalizedFormula, + FormulaLifecycle, + type InitializingFormula, +} from "./src/primitives/formula-lifecycle.js"; export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; export { type FormulaFn, isFormulaFn } from "./src/primitives/utils.js"; @@ -10,6 +14,7 @@ export { defineRuntime, getRuntime } from "./src/runtime.js"; export { intoReactive, isReactive, + isTagged, isTaggedReactive, read, type ReadValue, diff --git a/packages/universal/reactive/src/primitives/formula-lifecycle.ts b/packages/universal/reactive/src/primitives/formula-lifecycle.ts index df63cbe6..13500764 100644 --- a/packages/universal/reactive/src/primitives/formula-lifecycle.ts +++ b/packages/universal/reactive/src/primitives/formula-lifecycle.ts @@ -56,13 +56,14 @@ class FinalizedFormulaImpl { return this.#children; } - update(): { done: () => void } { + update(): InitializingFormula { const done = getRuntime().autotracking.start(); return { done: () => { this.#children = done(); this.#lastValidated = NOW.now; + return this; }, }; } diff --git a/packages/universal/reactive/src/utils.ts b/packages/universal/reactive/src/utils.ts index 636c4b36..09d2c585 100644 --- a/packages/universal/reactive/src/utils.ts +++ b/packages/universal/reactive/src/utils.ts @@ -8,10 +8,7 @@ import { Static } from "./primitives/static.js"; export type Reactive = interfaces.Reactive; -function is( - this: void, - value: T | interfaces.Reactive -): value is interfaces.Reactive { +function is(this: void, value: unknown): value is interfaces.Tagged { return !!( value && (typeof value === "object" || typeof value === "function") && @@ -19,6 +16,8 @@ function is( ); } +export const isTagged = is; + export function isReactive( this: void, value: unknown @@ -60,6 +59,8 @@ export function intoReactive( } } -function hasRead(value: object): value is { read: () => T } { +function hasRead( + value: object +): value is { read: (caller?: interfaces.CallStack) => T } { return "read" in value && typeof value.read === "function"; } diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index 0825e0dc..6f52fcb1 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -6,6 +6,7 @@ import type { Tagged, Unsubscribe, } from "@starbeam/interfaces"; +import { isTagged } from "@starbeam/reactive"; import { getTag, type Timestamp } from "@starbeam/tags"; import { NOW } from "@starbeam/tags"; @@ -59,9 +60,10 @@ export const SUBSCRIPTION_RUNTIME = new Mutations(); export class PublicTimeline { readonly on = { - change: (tagged: Tagged, ready: NotifyReady): Unsubscribe => { + change: (tagged: Tagged | Tag, ready: NotifyReady): Unsubscribe => { + const tag = isTagged(tagged) ? getTag(tagged) : tagged; const unsubscribes = new Set(); - for (const target of getTag(tagged).subscriptionTargets) { + for (const target of tag.subscriptionTargets) { unsubscribes.add(SUBSCRIPTION_RUNTIME.subscribe(target, ready)); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 415450d3..8876d50d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -560,9 +560,15 @@ importers: '@starbeam/reactive': specifier: workspace:^ version: link:../../universal/reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../../universal/resource '@starbeam/runtime': specifier: workspace:^ version: link:../../universal/runtime + '@starbeam/service': + specifier: workspace:^ + version: link:../../universal/service '@starbeam/tags': specifier: workspace:^ version: link:../../universal/tags @@ -715,9 +721,15 @@ importers: '@starbeam/preact': specifier: workspace:^ version: link:.. + '@starbeam/resource': + specifier: workspace:^ + version: link:../../../universal/resource '@starbeam/runtime': specifier: workspace:^ version: link:../../../universal/runtime + '@starbeam/service': + specifier: workspace:^ + version: link:../../../universal/service '@starbeam/universal': specifier: workspace:^ version: link:../../../universal/universal From 142416b1027c54ea5d1287de1e100cdbd9f74327 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 6 Apr 2023 18:06:05 -0700 Subject: [PATCH 27/46] Massive cleanup The first step towards GCing stale code after the refactor --- demos/preact-hello-world/package.json | 2 +- demos/preact/package.json | 2 +- demos/preact/src/components/db/Db-1.tsx | 2 +- demos/preact/src/components/db/Db-2.tsx | 2 +- demos/preact/src/components/db/Db-3.tsx | 2 +- demos/preact/src/components/db/Db-4.tsx | 2 +- demos/preact/src/components/db/Db-final.tsx | 2 +- demos/preact/src/components/db/table.ts | 2 +- .../components/formatter/DateFormatter-v1.tsx | 2 +- .../components/formatter/DateFormatter-v2.tsx | 2 +- .../components/formatter/DateFormatter-v3.tsx | 2 +- .../formatter/DateFormatterFinal.tsx | 2 +- demos/react-jsnation/package.json | 2 +- .../src/components/DataTable.tsx | 5 +- demos/react-jsnation/src/lib/table.ts | 21 +- demos/react-lite-query/package.json | 4 +- demos/react-lite-query/src/lib/fetch.ts | 2 +- demos/react-lite-query/src/lib/use-query.ts | 18 +- demos/react-query/package.json | 2 +- demos/react-query/src/lib/query.ts | 2 +- demos/react-stock-ticker/package.json | 2 +- demos/react-stock-ticker/src/store.ts | 2 +- demos/react/package.json | 2 +- demos/react/src/components/db/Db-1.tsx | 2 +- demos/react/src/components/db/Db-2.tsx | 2 +- demos/react/src/components/db/Db-3.tsx | 2 +- demos/react/src/components/db/Db-4.tsx | 2 +- demos/react/src/components/db/Db-final.tsx | 2 +- .../components/formatter/DateFormatter-v1.tsx | 2 +- .../components/formatter/DateFormatter-v2.tsx | 2 +- .../components/formatter/DateFormatter-v3.tsx | 2 +- .../formatter/DateFormatterFinal.tsx | 2 +- package.json | 2 +- packages/env.d.ts | 3 + packages/preact/preact/src/create.ts | 7 +- packages/preact/preact/src/frame.ts | 22 +- packages/preact/preact/src/options.ts | 13 +- packages/preact/preact/tests/services.spec.ts | 6 - packages/react/react/package.json | 2 +- packages/react/react/src/debug/warnings.ts | 40 +- packages/react/react/src/element.ts | 23 +- packages/react/react/src/ref.ts | 14 +- packages/react/react/src/use-reactive.ts | 22 +- packages/react/react/src/use-resource.ts | 3 +- packages/react/react/src/use-setup.ts | 13 +- packages/react/react/src/utils.ts | 12 +- .../react/react/tests/use-resource.spec.ts | 63 +- .../react/react/tests/use-service.spec.ts | 33 +- packages/react/react/tests/use-setup.spec.ts | 57 +- packages/react/test-utils/package.json | 2 + packages/react/test-utils/src/modes.ts | 127 +--- .../tests/use-lifecycle.spec.ts | 13 +- .../.eslintrc.json | 2 +- packages/universal/{js => collections}/.npmrc | 0 .../{js => collections}/CHANGELOG.md | 0 .../universal/{js => collections}/index.ts | 59 +- .../{js => collections}/package.json | 2 +- .../{js => collections}/rollup.config.mjs | 0 .../{js => collections}/src/array.ts | 24 +- .../{js => collections}/src/collection.ts | 74 +- .../{js => collections}/src/decorator.ts | 0 .../{js => collections}/src/iterable.ts | 105 +-- .../universal/{js => collections}/src/map.ts | 47 +- .../{js => collections}/src/mapper.ts | 0 .../{js => collections}/src/object.ts | 27 +- .../universal/{js => collections}/src/set.ts | 13 +- .../{js => collections}/tests/.eslintrc.json | 2 +- .../{js => collections}/tests/.npmrc | 0 .../{js => collections}/tests/CHANGELOG.md | 0 .../{js => collections}/tests/array.spec.ts | 2 +- .../{js => collections}/tests/map.spec.ts | 2 +- .../{js => collections}/tests/object.spec.ts | 2 +- .../{js => collections}/tests/package.json | 4 +- .../{js => collections}/tests/set.spec.ts | 2 +- .../{js => collections}/tests/support.ts | 0 .../{js => collections}/tests/tsconfig.json | 0 .../tests/weak-map.spec.ts | 2 +- .../tests/weak-set.spec.ts | 2 +- .../{js => collections}/tsconfig.json | 0 packages/universal/core-utils/index.ts | 23 +- packages/universal/core-utils/src/array.ts | 28 +- .../src/inspect/display-struct.ts | 0 .../src/inspect/inspect-support.ts | 5 +- .../src/inspect/json-value.ts | 0 packages/universal/core-utils/src/object.ts | 55 +- packages/universal/debug/index.ts | 65 +- packages/universal/debug/package.json | 2 + .../debug/src/call-stack/debug/index.ts | 3 + .../debug/src/call-stack/debug/module.ts | 125 ++++ .../debug/src/call-stack/debug/stack.ts | 228 ++++++ .../universal/debug/src/call-stack/prod.ts | 3 + .../universal/debug/src/component/stack.ts | 180 ----- packages/universal/debug/src/debug.ts | 22 + .../universal/debug/src/description/README.md | 4 + .../debug/src/description/debug/describe.ts | 385 +++++++++++ .../src/description/debug/description.ts | 145 ++++ .../debug/src/description/debug/index.ts | 4 + .../universal/debug/src/description/impl.ts | 651 ------------------ .../debug/src/description/interface.ts | 7 + .../universal/debug/src/description/prod.ts | 3 + packages/universal/debug/src/entry-point.ts | 19 - packages/universal/debug/src/logged.ts | 21 - packages/universal/debug/src/logger.ts | 137 ---- packages/universal/debug/src/message.ts | 171 ----- packages/universal/debug/src/module.ts | 287 -------- packages/universal/debug/src/stack.ts | 599 ---------------- packages/universal/debug/src/tag.ts | 46 +- packages/universal/debug/src/timeline.ts | 351 ---------- .../universal/debug/tests/display.spec.ts | 72 -- .../debug/tests/node-inspect.spec.ts | 2 +- packages/universal/debug/tests/package.json | 3 +- packages/universal/debug/tests/stack.spec.ts | 20 +- packages/universal/interfaces/.eslintrc.json | 2 +- packages/universal/interfaces/index.d.ts | 69 -- packages/universal/interfaces/index.ts | 32 + packages/universal/interfaces/package.json | 11 +- .../universal/interfaces/src/aliases.d.ts | 1 - .../src/debug-protocol/protocol.d.ts | 7 - .../interfaces/src/debug-protocol/tree.d.ts | 85 --- .../interfaces/src/debug/call-stack.ts | 24 + .../interfaces/src/debug/debug-runtime.ts | 22 + .../interfaces/src/debug/description.ts | 116 ++++ .../universal/interfaces/src/description.d.ts | 243 ------- packages/universal/interfaces/src/diff.d.ts | 4 - packages/universal/interfaces/src/frame.d.ts | 22 - .../src/{protocol.d.ts => protocol.ts} | 78 +-- .../src/{runtime.d.ts => runtime.ts} | 28 +- packages/universal/interfaces/src/stack.d.ts | 51 -- .../src/{timestamp.d.ts => timestamp.ts} | 0 packages/universal/interfaces/src/utils.d.ts | 1 - packages/universal/interfaces/src/utils.ts | 7 + packages/universal/interfaces/tsconfig.json | 2 +- packages/universal/modifier/package.json | 1 + packages/universal/modifier/src/modifier.ts | 14 +- packages/universal/reactive/index.ts | 3 +- packages/universal/reactive/package.json | 1 - .../universal/reactive/src/primitives/base.ts | 8 +- .../reactive/src/primitives/cached.ts | 24 +- .../universal/reactive/src/primitives/cell.ts | 29 +- .../reactive/src/primitives/delegate.ts | 28 +- .../src/primitives/formula-lifecycle.ts | 25 +- .../reactive/src/primitives/formula.ts | 19 +- .../reactive/src/primitives/marker.ts | 20 +- .../reactive/src/primitives/static.ts | 12 +- .../reactive/src/primitives/utils.ts | 12 +- packages/universal/reactive/src/runtime.ts | 17 +- packages/universal/reactive/src/utils.ts | 21 +- packages/universal/resource/src/api.ts | 3 +- .../universal/resource/src/resource-list.ts | 17 +- packages/universal/resource/src/resource.ts | 19 +- .../universal/resource/tests/package.json | 2 +- .../resource/tests/resource-list.spec.ts | 4 +- packages/universal/runtime/index.ts | 5 +- packages/universal/runtime/src/define.ts | 24 +- .../runtime/src/lifetime/object-lifetime.ts | 2 +- .../universal/runtime/src/timeline/debug.ts | 10 - .../runtime/src/timeline/subscriptions.ts | 16 +- .../universal/runtime/src/timeline/tracker.ts | 18 +- .../universal/runtime/tests/consume.spec.ts | 9 +- .../universal/runtime/tests/protocol.spec.ts | 35 +- .../runtime/tests/subscribing.spec.ts | 14 +- .../runtime/tests/support/testing.ts | 32 +- packages/universal/service/src/service.ts | 6 +- packages/universal/service/tests/package.json | 2 +- packages/universal/tags/index.ts | 25 +- packages/universal/tags/package.json | 2 +- packages/universal/tags/src/tag.ts | 329 +++------ packages/universal/tags/src/tagged.ts | 38 +- packages/universal/tags/src/timestamp.ts | 2 +- packages/universal/test-utils/tsconfig.json | 12 - packages/universal/universal/CONCEPTS.md | 2 +- packages/universal/universal/index.ts | 12 - .../universal/universal/src/debug-renderer.ts | 11 +- .../universal/src/reactive-core/custom.ts | 51 -- .../reactive-core/higher-level/freshness.ts | 14 +- .../universal/src/reactive-core/reactive.ts | 67 -- .../universal/src/reactive-core/variants.ts | 127 ++-- .../universal/universal/tests/custom.spec.ts | 182 ----- .../universal/universal/tests/formula.spec.ts | 2 +- .../tests/higher-level/formula-list.spec.ts | 2 +- .../universal/universal/tests/package.json | 2 +- .../universal/tests/polled-formula.spec.ts | 2 +- .../universal/tests/variants.spec.ts | 9 +- packages/x/devtool/src/log/cell.tsx | 2 +- packages/x/devtool/src/log/describe.tsx | 2 +- packages/x/devtool/src/log/frame.tsx | 2 +- packages/x/devtool/src/log/log.tsx | 7 +- .../x/devtool/src/single/single-reactive.tsx | 7 +- packages/x/store/package.json | 4 +- packages/x/store/src/flat.ts | 24 +- packages/x/store/src/table.ts | 35 +- packages/x/vanilla/package.json | 1 + packages/x/vanilla/src/dom.ts | 168 ++--- pnpm-lock.yaml | 224 +++--- vitest.config.ts | 1 + workspace/build/src/config.js | 10 +- workspace/eslint/src/base.js | 3 + workspace/reporter/src/table.ts | 8 +- .../test-utils}/.eslintrc.json | 2 +- .../universal => workspace}/test-utils/.npmrc | 0 .../test-utils/index.ts | 0 .../test-utils/package.json | 0 .../test-utils/rollup.config.mjs | 0 .../test-utils/src/test-resource.ts | 0 .../test-utils/src/utils.ts | 0 .../test-utils/src/vitest.ts | 0 workspace/test-utils/tsconfig.json | 12 + 207 files changed, 2423 insertions(+), 4855 deletions(-) rename packages/universal/{test-utils => collections}/.eslintrc.json (72%) rename packages/universal/{js => collections}/.npmrc (100%) rename packages/universal/{js => collections}/CHANGELOG.md (100%) rename packages/universal/{js => collections}/index.ts (66%) rename packages/universal/{js => collections}/package.json (96%) rename packages/universal/{js => collections}/rollup.config.mjs (100%) rename packages/universal/{js => collections}/src/array.ts (88%) rename packages/universal/{js => collections}/src/collection.ts (77%) rename packages/universal/{js => collections}/src/decorator.ts (100%) rename packages/universal/{js => collections}/src/iterable.ts (75%) rename packages/universal/{js => collections}/src/map.ts (71%) rename packages/universal/{js => collections}/src/mapper.ts (100%) rename packages/universal/{js => collections}/src/object.ts (91%) rename packages/universal/{js => collections}/src/set.ts (76%) rename packages/universal/{js => collections}/tests/.eslintrc.json (68%) rename packages/universal/{js => collections}/tests/.npmrc (100%) rename packages/universal/{js => collections}/tests/CHANGELOG.md (100%) rename packages/universal/{js => collections}/tests/array.spec.ts (98%) rename packages/universal/{js => collections}/tests/map.spec.ts (99%) rename packages/universal/{js => collections}/tests/object.spec.ts (99%) rename packages/universal/{js => collections}/tests/package.json (73%) rename packages/universal/{js => collections}/tests/set.spec.ts (98%) rename packages/universal/{js => collections}/tests/support.ts (100%) rename packages/universal/{js => collections}/tests/tsconfig.json (100%) rename packages/universal/{js => collections}/tests/weak-map.spec.ts (98%) rename packages/universal/{js => collections}/tests/weak-set.spec.ts (96%) rename packages/universal/{js => collections}/tsconfig.json (100%) rename packages/universal/{debug => core-utils}/src/inspect/display-struct.ts (100%) rename packages/universal/{debug => core-utils}/src/inspect/inspect-support.ts (97%) rename packages/universal/{debug => core-utils}/src/inspect/json-value.ts (100%) create mode 100644 packages/universal/debug/src/call-stack/debug/index.ts create mode 100644 packages/universal/debug/src/call-stack/debug/module.ts create mode 100644 packages/universal/debug/src/call-stack/debug/stack.ts create mode 100644 packages/universal/debug/src/call-stack/prod.ts delete mode 100644 packages/universal/debug/src/component/stack.ts create mode 100644 packages/universal/debug/src/debug.ts create mode 100644 packages/universal/debug/src/description/debug/describe.ts create mode 100644 packages/universal/debug/src/description/debug/description.ts create mode 100644 packages/universal/debug/src/description/debug/index.ts delete mode 100644 packages/universal/debug/src/description/impl.ts create mode 100644 packages/universal/debug/src/description/interface.ts create mode 100644 packages/universal/debug/src/description/prod.ts delete mode 100644 packages/universal/debug/src/entry-point.ts delete mode 100644 packages/universal/debug/src/logged.ts delete mode 100644 packages/universal/debug/src/logger.ts delete mode 100644 packages/universal/debug/src/message.ts delete mode 100644 packages/universal/debug/src/module.ts delete mode 100644 packages/universal/debug/src/stack.ts delete mode 100644 packages/universal/debug/src/timeline.ts delete mode 100644 packages/universal/debug/tests/display.spec.ts delete mode 100644 packages/universal/interfaces/index.d.ts create mode 100644 packages/universal/interfaces/index.ts delete mode 100644 packages/universal/interfaces/src/aliases.d.ts delete mode 100644 packages/universal/interfaces/src/debug-protocol/protocol.d.ts delete mode 100644 packages/universal/interfaces/src/debug-protocol/tree.d.ts create mode 100644 packages/universal/interfaces/src/debug/call-stack.ts create mode 100644 packages/universal/interfaces/src/debug/debug-runtime.ts create mode 100644 packages/universal/interfaces/src/debug/description.ts delete mode 100644 packages/universal/interfaces/src/description.d.ts delete mode 100644 packages/universal/interfaces/src/diff.d.ts delete mode 100644 packages/universal/interfaces/src/frame.d.ts rename packages/universal/interfaces/src/{protocol.d.ts => protocol.ts} (76%) rename packages/universal/interfaces/src/{runtime.d.ts => runtime.ts} (58%) delete mode 100644 packages/universal/interfaces/src/stack.d.ts rename packages/universal/interfaces/src/{timestamp.d.ts => timestamp.ts} (100%) delete mode 100644 packages/universal/interfaces/src/utils.d.ts create mode 100644 packages/universal/interfaces/src/utils.ts delete mode 100644 packages/universal/runtime/src/timeline/debug.ts delete mode 100644 packages/universal/test-utils/tsconfig.json delete mode 100644 packages/universal/universal/src/reactive-core/custom.ts delete mode 100644 packages/universal/universal/src/reactive-core/reactive.ts delete mode 100644 packages/universal/universal/tests/custom.spec.ts rename {packages/universal/js => workspace/test-utils}/.eslintrc.json (75%) rename {packages/universal => workspace}/test-utils/.npmrc (100%) rename {packages/universal => workspace}/test-utils/index.ts (100%) rename {packages/universal => workspace}/test-utils/package.json (100%) rename {packages/universal => workspace}/test-utils/rollup.config.mjs (100%) rename {packages/universal => workspace}/test-utils/src/test-resource.ts (100%) rename {packages/universal => workspace}/test-utils/src/utils.ts (100%) rename {packages/universal => workspace}/test-utils/src/vitest.ts (100%) create mode 100644 workspace/test-utils/tsconfig.json diff --git a/demos/preact-hello-world/package.json b/demos/preact-hello-world/package.json index 7ee4c170..99a33f19 100644 --- a/demos/preact-hello-world/package.json +++ b/demos/preact-hello-world/package.json @@ -36,7 +36,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/preact": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", diff --git a/demos/preact/package.json b/demos/preact/package.json index 5e64ed0a..905f544a 100644 --- a/demos/preact/package.json +++ b/demos/preact/package.json @@ -36,7 +36,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/preact": "workspace:^", "@starbeam/universal": "workspace:^", "preact": "^10.11.3", diff --git a/demos/preact/src/components/db/Db-1.tsx b/demos/preact/src/components/db/Db-1.tsx index 1410a0d1..fda6d1f8 100644 --- a/demos/preact/src/components/db/Db-1.tsx +++ b/demos/preact/src/components/db/Db-1.tsx @@ -1,4 +1,4 @@ -import { object } from "@starbeam/js"; +import { object } from "@starbeam/collections"; import { create } from "@starbeam/preact"; import type { JSX } from "preact/jsx-runtime"; diff --git a/demos/preact/src/components/db/Db-2.tsx b/demos/preact/src/components/db/Db-2.tsx index d61a9e47..0b6d66f4 100644 --- a/demos/preact/src/components/db/Db-2.tsx +++ b/demos/preact/src/components/db/Db-2.tsx @@ -1,5 +1,5 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { create } from "@starbeam/preact"; import type { JSX } from "preact/jsx-runtime"; diff --git a/demos/preact/src/components/db/Db-3.tsx b/demos/preact/src/components/db/Db-3.tsx index b9ea2b0d..8b5ff668 100644 --- a/demos/preact/src/components/db/Db-3.tsx +++ b/demos/preact/src/components/db/Db-3.tsx @@ -1,5 +1,5 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { create } from "@starbeam/preact"; import type { JSX } from "preact/jsx-runtime"; diff --git a/demos/preact/src/components/db/Db-4.tsx b/demos/preact/src/components/db/Db-4.tsx index a98769be..73001f82 100644 --- a/demos/preact/src/components/db/Db-4.tsx +++ b/demos/preact/src/components/db/Db-4.tsx @@ -1,5 +1,5 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { create } from "@starbeam/preact"; import type { JSX } from "preact"; diff --git a/demos/preact/src/components/db/Db-final.tsx b/demos/preact/src/components/db/Db-final.tsx index 4e1cb6d7..151f2ca3 100644 --- a/demos/preact/src/components/db/Db-final.tsx +++ b/demos/preact/src/components/db/Db-final.tsx @@ -1,5 +1,5 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { create } from "@starbeam/preact"; import type { JSX } from "preact/jsx-runtime"; diff --git a/demos/preact/src/components/db/table.ts b/demos/preact/src/components/db/table.ts index 2adaa902..aad34f62 100644 --- a/demos/preact/src/components/db/table.ts +++ b/demos/preact/src/components/db/table.ts @@ -1,4 +1,4 @@ -import { object } from "@starbeam/js"; +import { object } from "@starbeam/collections"; export class Table { #rows: Record = object({}, "rows"); diff --git a/demos/preact/src/components/formatter/DateFormatter-v1.tsx b/demos/preact/src/components/formatter/DateFormatter-v1.tsx index 685ee8f1..5b755d32 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v1.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v1.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { create } from "@starbeam/preact"; import { Formula } from "@starbeam/universal"; import type { JSX } from "preact"; diff --git a/demos/preact/src/components/formatter/DateFormatter-v2.tsx b/demos/preact/src/components/formatter/DateFormatter-v2.tsx index 3b28e618..f6d92705 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v2.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v2.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { use } from "@starbeam/preact"; import { type ResourceBlueprint, Resource, Static } from "@starbeam/universal"; import type { JSX } from "preact"; diff --git a/demos/preact/src/components/formatter/DateFormatter-v3.tsx b/demos/preact/src/components/formatter/DateFormatter-v3.tsx index e23cfec3..1cb68e97 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v3.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v3.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { create, use } from "@starbeam/preact"; import type { Reactive, ResourceBlueprint } from "@starbeam/universal"; import { Cell, Resource, Static } from "@starbeam/universal"; diff --git a/demos/preact/src/components/formatter/DateFormatterFinal.tsx b/demos/preact/src/components/formatter/DateFormatterFinal.tsx index 6530870f..0422a261 100644 --- a/demos/preact/src/components/formatter/DateFormatterFinal.tsx +++ b/demos/preact/src/components/formatter/DateFormatterFinal.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { create, use } from "@starbeam/preact"; import type { ResourceBlueprint } from "@starbeam/universal"; import { type Reactive, Cell, Resource } from "@starbeam/universal"; diff --git a/demos/react-jsnation/package.json b/demos/react-jsnation/package.json index 637d93e1..bb7e1163 100644 --- a/demos/react-jsnation/package.json +++ b/demos/react-jsnation/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@starbeam/debug": "workspace:^", - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/universal": "workspace:^", "purecss": "3.0.0", diff --git a/demos/react-jsnation/src/components/DataTable.tsx b/demos/react-jsnation/src/components/DataTable.tsx index b0366ef8..9f01206c 100644 --- a/demos/react-jsnation/src/components/DataTable.tsx +++ b/demos/react-jsnation/src/components/DataTable.tsx @@ -1,13 +1,10 @@ -import { LOGGER, LogLevel } from "@starbeam/debug"; import { useProp, useReactive, useSetup } from "@starbeam/react"; import { Cell, Formula } from "@starbeam/universal"; import type { FormEvent } from "react"; -import { type Person, People } from "../lib/people.js"; +import { People, type Person } from "../lib/people.js"; import { type Row, Table } from "../lib/table.js"; -LOGGER.level = LogLevel.Debug; - export default function (props: { locale: string }): JSX.Element { const locale = useProp(props.locale, "props.locale"); diff --git a/demos/react-jsnation/src/lib/table.ts b/demos/react-jsnation/src/lib/table.ts index 78eff9e6..0e4fa20c 100644 --- a/demos/react-jsnation/src/lib/table.ts +++ b/demos/react-jsnation/src/lib/table.ts @@ -1,5 +1,4 @@ -import { entryPoint } from "@starbeam/debug"; -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; export type Row = { id: string; @@ -58,16 +57,14 @@ export class Query { } get rows(): Row[] { - return entryPoint(() => { - const filtered = this.#table.rows.filter((row) => - this.#filters.every((filter) => filter(row)) - ); + const filtered = this.#table.rows.filter((row) => + this.#filters.every((filter) => filter(row)) + ); - if (this.#sort) { - return filtered.sort(this.#sort); - } else { - return filtered; - } - }); + if (this.#sort) { + return filtered.sort(this.#sort); + } else { + return filtered; + } } } diff --git a/demos/react-lite-query/package.json b/demos/react-lite-query/package.json index d2f79a96..6be25053 100644 --- a/demos/react-lite-query/package.json +++ b/demos/react-lite-query/package.json @@ -30,9 +30,11 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/collections": "workspace:^", "@starbeam/debug": "workspace:^", - "@starbeam/js": "workspace:^", + "@starbeam/interfaces": "workspace:^", "@starbeam/react": "workspace:^", + "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^", "@starbeamx/devtool": "workspace:^", diff --git a/demos/react-lite-query/src/lib/fetch.ts b/demos/react-lite-query/src/lib/fetch.ts index 8a082fac..80110936 100644 --- a/demos/react-lite-query/src/lib/fetch.ts +++ b/demos/react-lite-query/src/lib/fetch.ts @@ -1,5 +1,5 @@ import { type Description, type Stack, callerStack } from "@starbeam/debug"; -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { Cell } from "@starbeam/universal"; import { isPresent, verified } from "@starbeam/verify"; diff --git a/demos/react-lite-query/src/lib/use-query.ts b/demos/react-lite-query/src/lib/use-query.ts index c5e6fe8f..bc8df6af 100644 --- a/demos/react-lite-query/src/lib/use-query.ts +++ b/demos/react-lite-query/src/lib/use-query.ts @@ -1,9 +1,6 @@ -import { - type Description, - callerStack, - descriptionFrom, -} from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces/index.js"; import { useSetup } from "@starbeam/react"; +import { RUNTIME } from "@starbeam/runtime"; import type { AsyncData, Query } from "./fetch.js"; import { QUERIES } from "./fetch.js"; @@ -13,14 +10,9 @@ export default function useQuery( query: Query, description?: string | Description ): AsyncData { - const desc = descriptionFrom({ - type: "resource", - api: { - package: "@starbeam-demos/react-lite-query", - name: "useQuery", - }, - fromUser: description ?? "QUERIES", - }).detail("query", [key]); + const desc = RUNTIME.debug + .desc("resource", description, "useQuery") + ?.detail("formula", "query", [key]); return useSetup(({ on }) => { on.idle(() => { diff --git a/demos/react-query/package.json b/demos/react-query/package.json index 10f6c38c..2e464141 100644 --- a/demos/react-query/package.json +++ b/demos/react-query/package.json @@ -35,7 +35,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeamx/devtool": "workspace:^", diff --git a/demos/react-query/src/lib/query.ts b/demos/react-query/src/lib/query.ts index f4b9d653..7bfda573 100644 --- a/demos/react-query/src/lib/query.ts +++ b/demos/react-query/src/lib/query.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { Cell, Freshness } from "@starbeam/universal"; import { CanceledError } from "axios"; diff --git a/demos/react-stock-ticker/package.json b/demos/react-stock-ticker/package.json index d42515c1..8405f4e4 100644 --- a/demos/react-stock-ticker/package.json +++ b/demos/react-stock-ticker/package.json @@ -30,7 +30,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeamx/devtool": "workspace:*", diff --git a/demos/react-stock-ticker/src/store.ts b/demos/react-stock-ticker/src/store.ts index 4b80beea..88f32521 100644 --- a/demos/react-stock-ticker/src/store.ts +++ b/demos/react-stock-ticker/src/store.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { Cell } from "@starbeam/universal"; import type { Stock } from "./lib/api/interfaces.js"; diff --git a/demos/react/package.json b/demos/react/package.json index dadd06ec..7a9eb175 100644 --- a/demos/react/package.json +++ b/demos/react/package.json @@ -35,7 +35,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/universal": "workspace:^", "purecss": "3.0.0", diff --git a/demos/react/src/components/db/Db-1.tsx b/demos/react/src/components/db/Db-1.tsx index 41635a26..91139cab 100644 --- a/demos/react/src/components/db/Db-1.tsx +++ b/demos/react/src/components/db/Db-1.tsx @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import type { FormEvent } from "react"; diff --git a/demos/react/src/components/db/Db-2.tsx b/demos/react/src/components/db/Db-2.tsx index bd6f3280..59957420 100644 --- a/demos/react/src/components/db/Db-2.tsx +++ b/demos/react/src/components/db/Db-2.tsx @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import type { FormEvent } from "react"; diff --git a/demos/react/src/components/db/Db-3.tsx b/demos/react/src/components/db/Db-3.tsx index ed79e31d..604f6199 100644 --- a/demos/react/src/components/db/Db-3.tsx +++ b/demos/react/src/components/db/Db-3.tsx @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import type { FormEvent } from "react"; diff --git a/demos/react/src/components/db/Db-4.tsx b/demos/react/src/components/db/Db-4.tsx index 06531b93..aa45b5d7 100644 --- a/demos/react/src/components/db/Db-4.tsx +++ b/demos/react/src/components/db/Db-4.tsx @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import type { FormEvent } from "react"; diff --git a/demos/react/src/components/db/Db-final.tsx b/demos/react/src/components/db/Db-final.tsx index fe493791..ebca1896 100644 --- a/demos/react/src/components/db/Db-final.tsx +++ b/demos/react/src/components/db/Db-final.tsx @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { useProp, useSetup } from "@starbeam/react"; import type { FormEvent } from "react"; diff --git a/demos/react/src/components/formatter/DateFormatter-v1.tsx b/demos/react/src/components/formatter/DateFormatter-v1.tsx index 0266606f..30673975 100644 --- a/demos/react/src/components/formatter/DateFormatter-v1.tsx +++ b/demos/react/src/components/formatter/DateFormatter-v1.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import type { Reactive } from "@starbeam/universal"; import { Formula } from "@starbeam/universal"; diff --git a/demos/react/src/components/formatter/DateFormatter-v2.tsx b/demos/react/src/components/formatter/DateFormatter-v2.tsx index 3f88b941..931a1ced 100644 --- a/demos/react/src/components/formatter/DateFormatter-v2.tsx +++ b/demos/react/src/components/formatter/DateFormatter-v2.tsx @@ -1,4 +1,4 @@ -import * as js from "@starbeam/js"; +import * as js from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import type { ResourceBlueprint } from "@starbeam/universal"; import { Resource } from "@starbeam/universal"; diff --git a/demos/react/src/components/formatter/DateFormatter-v3.tsx b/demos/react/src/components/formatter/DateFormatter-v3.tsx index 5fe7d475..549d067e 100644 --- a/demos/react/src/components/formatter/DateFormatter-v3.tsx +++ b/demos/react/src/components/formatter/DateFormatter-v3.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import { type Reactive, diff --git a/demos/react/src/components/formatter/DateFormatterFinal.tsx b/demos/react/src/components/formatter/DateFormatterFinal.tsx index aa3297c2..9f7648ab 100644 --- a/demos/react/src/components/formatter/DateFormatterFinal.tsx +++ b/demos/react/src/components/formatter/DateFormatterFinal.tsx @@ -1,4 +1,4 @@ -import js from "@starbeam/js"; +import js from "@starbeam/collections"; import { use, useCell, useReactive } from "@starbeam/react"; import { type Reactive, diff --git a/package.json b/package.json index f5212f34..714ae5f4 100644 --- a/package.json +++ b/package.json @@ -178,6 +178,6 @@ }, "volta": { "node": "19.8.1", - "pnpm": "8.1.0" + "pnpm": "8.1.1" } } diff --git a/packages/env.d.ts b/packages/env.d.ts index 6db910aa..cb349c63 100644 --- a/packages/env.d.ts +++ b/packages/env.d.ts @@ -1,3 +1,6 @@ +import "vitest/importMeta.js"; +import "vite/client"; + interface ImportMeta { env: { PROD: boolean | ""; diff --git a/packages/preact/preact/src/create.ts b/packages/preact/preact/src/create.ts index 1658086e..9619ef08 100644 --- a/packages/preact/preact/src/create.ts +++ b/packages/preact/preact/src/create.ts @@ -1,4 +1,5 @@ -import { Desc, type Description } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { Cell } from "@starbeam/universal"; import { useMemo } from "preact/hooks"; @@ -8,8 +9,8 @@ export function create(Reactive: () => T): T { export function createCell( value: T, - description?: string | Description + description?: string | Description | undefined ): Cell { - const desc = Desc("cell", description); + const desc = RUNTIME.Desc?.("cell", description, "createCell"); return create(() => Cell(value, { description: desc })); } diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index 8c20fcc0..1ee419a2 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -1,10 +1,10 @@ import { getLast } from "@starbeam/core-utils"; -import { Desc, type Description } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; import type { InternalComponent } from "@starbeam/preact-utils"; import type { FinalizedFormula, InitializingFormula } from "@starbeam/reactive"; import { FormulaLifecycle } from "@starbeam/reactive"; import { PUBLIC_TIMELINE, RUNTIME, type Unsubscribe } from "@starbeam/runtime"; -import { FormulaTag } from "@starbeam/tags"; +import { createFormulaTag, type FormulaTag } from "@starbeam/tags"; import { expected, isPresent, verify } from "@starbeam/verify"; export class ComponentFrame { @@ -16,11 +16,14 @@ export class ComponentFrame { static #frames = new WeakMap(); static #stack: InternalComponent[] = []; - static start(component: InternalComponent, description: Description): void { + static start( + component: InternalComponent, + description: Description | undefined + ): void { let frame = ComponentFrame.#frames.get(component); if (!frame) { - frame = new ComponentFrame(null, null, null); + frame = new ComponentFrame(null, null, null, description); ComponentFrame.#frames.set(component, frame); } @@ -72,18 +75,19 @@ export class ComponentFrame { private constructor( frame: FinalizedFormula | null, active: InitializingFormula | null, - subscribed: Unsubscribe | null + subscribed: Unsubscribe | null, + description: Description | undefined ) { this.#frame = frame; this.#active = active; - this.#tag = FormulaTag.create( - Desc("external", "preact:component"), - () => this.#frame?.children() ?? [] + this.#tag = createFormulaTag( + RUNTIME.Desc?.("formula", description), + () => this.#frame?.children() ?? new Set() ); this.#subscription = subscribed; } - #start(description: Description): void { + #start(description: Description | undefined): void { if (this.#frame) { this.#active = this.#frame.update(); // this.#active = TIMELINE.frame.update(this.#frame); diff --git a/packages/preact/preact/src/options.ts b/packages/preact/preact/src/options.ts index 200b7a3f..0f28fe1f 100644 --- a/packages/preact/preact/src/options.ts +++ b/packages/preact/preact/src/options.ts @@ -1,10 +1,9 @@ -import { descriptionFrom } from "@starbeam/debug"; import type { InternalComponent, InternalElement, } from "@starbeam/preact-utils"; import { Plugin } from "@starbeam/preact-utils"; -import { isReactive } from "@starbeam/reactive"; +import { isReactive, RUNTIME } from "@starbeam/reactive"; import { CONTEXT, LIFETIME } from "@starbeam/runtime"; import type { ComponentType } from "preact"; @@ -41,11 +40,11 @@ export const setup = Plugin((on) => { ComponentFrame.start( component, - descriptionFrom({ - api: "preact", - type: "implementation", - fromUser: componentName(component.fn), - }) + RUNTIME.Desc?.( + "formula", + componentName(component.fn), + "preact.componentWillRender" + ) ); }); diff --git a/packages/preact/preact/tests/services.spec.ts b/packages/preact/preact/tests/services.spec.ts index 7099b770..585f839e 100644 --- a/packages/preact/preact/tests/services.spec.ts +++ b/packages/preact/preact/tests/services.spec.ts @@ -1,8 +1,6 @@ // @vitest-environment jsdom import { service, setup } from "@starbeam/preact"; -import type { Resource } from "@starbeam/resource"; -import { getTag } from "@starbeam/tags"; import { html, type HtmlNode, @@ -68,7 +66,3 @@ describe("services", () => { }) ); }); - -function id(service: Resource): string { - return JSON.stringify(getTag(service).id); -} diff --git a/packages/react/react/package.json b/packages/react/react/package.json index 079a208e..cbfea9f7 100644 --- a/packages/react/react/package.json +++ b/packages/react/react/package.json @@ -31,7 +31,7 @@ "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/modifier": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/resource": "workspace:^", diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index 97f7badc..ab240bd2 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -5,13 +5,15 @@ import { isRendering } from "@starbeam/use-strict-lifecycle"; let WARNED = false; if (import.meta.env.DEV) { - RUNTIME.debug.untrackedReadBarrier((tag, stack) => { + RUNTIME.debug?.untrackedReadBarrier((tag, _caller) => { if (isRendering()) { if (!WARNED) { WARNED = true; - const description = tag.description.userFacing; - const caller = stack.caller; + const description = RUNTIME.debug?.getUserFacing(tag.description); + const fullName = description + ? RUNTIME.debug?.describe(description) ?? "an unknown reactive value" + : "an unknown reactive value"; const pad = Math.max( ...["Created: ", "Accessed: "].map((s) => s.length) @@ -30,18 +32,19 @@ if (import.meta.env.DEV) { [ ["Created: ".padEnd(pad, "…"), "color:#666"], " ", - [description.fullName, "color:#6a6"], - ], - [ - [" ".repeat(pad), "color:#666"], - " ", - [description.frame?.link() ?? "", "color:#6a6"], - ], - [ - ["Accessed: ".padEnd(pad, "…"), "color:#666"], - " ", - [caller?.link() ?? "", "color:#6a6"], + [fullName, "color:#6a6"], ], + // FIXME: frame.link() + // [ + // [" ".repeat(pad), "color:#666"], + // " ", + // [description.frame?.link() ?? "", "color:#6a6"], + // ], + // [ + // ["Accessed: ".padEnd(pad, "…"), "color:#666"], + // " ", + // [caller?.link() ?? "", "color:#6a6"], + // ], "", [ [ @@ -74,9 +77,12 @@ if (import.meta.env.DEV) { console.warn(...message); - console.groupCollapsed("Complete stack trace"); - console.log(stack.stack); - console.groupEnd(); + // FIXME: caller.stack + // if (caller) { + // console.groupCollapsed("Complete stack trace"); + // console.log(caller.stack); + // console.groupEnd(); + // } } throw Error( diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 26b3ee4f..4e1d3be9 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,6 +1,7 @@ import type { browser } from "@domtree/flavors"; -import { type DebugListener, Desc, type Description } from "@starbeam/debug"; -import type { Reactive, Tagged } from "@starbeam/interfaces"; +import type { DebugListener } from "@starbeam/debug"; +import type { Description, Reactive, Tagged } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import type { IntoResourceBlueprint, Resource } from "@starbeam/resource"; import * as resource from "@starbeam/resource"; import { @@ -151,7 +152,7 @@ export class ReactiveElement implements CleanupTarget { static create( notify: () => void, context: ReactApp | null, - description: Description + description: Description | undefined ): ReactiveElement { return new ReactiveElement( notify, @@ -175,7 +176,7 @@ export class ReactiveElement implements CleanupTarget { static activate( notify: () => void, context: ReactApp | null, - description: Description, + description: Description | undefined, prev: ReactiveElement | undefined ): ReactiveElement { if (prev) { @@ -207,7 +208,7 @@ export class ReactiveElement implements CleanupTarget { #context: ReactApp | null; #debugLifecycle: DebugLifecycle | null = null; #refs: Refs; - readonly #description: Description; + readonly #description: Description | undefined; readonly on: OnLifecycle; @@ -216,7 +217,7 @@ export class ReactiveElement implements CleanupTarget { context: ReactApp | null, lifecycle: Lifecycle, refs: Refs, - description: Description + description: Description | undefined ) { this.#lifecycle = lifecycle; this.#context = context; @@ -237,7 +238,7 @@ export class ReactiveElement implements CleanupTarget { blueprint: IntoResourceBlueprint, description?: string | Description | undefined ): Resource => { - const desc = Desc("service", description); + const desc = RUNTIME.Desc?.("service", description, "UseSetup.service"); const context = this.#context; if (context === null) { @@ -330,7 +331,7 @@ interface OnLifecycle extends OnCleanup { } class Lifecycle { - static create(description: Description): Lifecycle { + static create(description: Description | undefined): Lifecycle { return new Lifecycle(new Set(), new Set(), description); } @@ -349,7 +350,7 @@ class Lifecycle { static on( lifecycle: Lifecycle, instance: T, - _elementDescription: Description + _elementDescription: Description | undefined ): OnLifecycle { LIFETIME.link(instance, lifecycle); @@ -369,12 +370,12 @@ class Lifecycle { readonly #idle: Set; readonly #layout: Set; - readonly #description: Description; + readonly #description: Description | undefined; private constructor( idle: Set, layout: Set, - description: Description + description: Description | undefined ) { this.#idle = idle; this.#layout = layout; diff --git a/packages/react/react/src/ref.ts b/packages/react/react/src/ref.ts index 896d1ac6..0313634b 100644 --- a/packages/react/react/src/ref.ts +++ b/packages/react/react/src/ref.ts @@ -1,6 +1,7 @@ import type { anydom, browser } from "@domtree/flavors"; -import { type Description, descriptionFrom } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; import { ElementPlaceholder } from "@starbeam/modifier"; +import { RUNTIME } from "@starbeam/reactive"; import { expected, isEqual, @@ -62,18 +63,11 @@ type ElementType = abstract new (...args: any[]) => E; export function ref( kind: ElementType, - description?: string | Description + description?: string | Description | undefined ): ReactElementRef { const placeholder = ElementPlaceholder( kind, - descriptionFrom({ - type: "formula", - api: { - package: "@starbeam/react", - name: "ref", - }, - fromUser: description, - }) + RUNTIME.Desc?.("formula", description, "ref") ); const verifier = ClassVerifier(kind); diff --git a/packages/react/react/src/use-reactive.ts b/packages/react/react/src/use-reactive.ts index 66023adf..fc81391e 100644 --- a/packages/react/react/src/use-reactive.ts +++ b/packages/react/react/src/use-reactive.ts @@ -1,6 +1,6 @@ -import { Desc, type Description } from "@starbeam/debug"; +import type { Description, Reactive } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { PUBLIC_TIMELINE } from "@starbeam/runtime"; -import type { Reactive } from "@starbeam/universal"; import { Cell, Formula, @@ -28,7 +28,7 @@ export function useReactive( computeFn: () => T, description?: string | Description | undefined ): T { - const desc = Desc("formula", description); + const desc = RUNTIME.Desc?.("formula", description); const notify = useNotify(); @@ -71,7 +71,7 @@ export function useCell( value: T, description?: Description | string ): Cell { - const desc = Desc("cell", description); + const desc = RUNTIME.Desc?.("cell", description); return useSetup(() => ({ cell: Cell(value, { description: desc }) })).cell; } @@ -91,15 +91,23 @@ export class MountedReactive { #value: Reactive | undefined; #owner: object | undefined = undefined; - private constructor(initial: T, description: Description) { + private constructor(initial: T, description: Description | undefined) { this.#initial = initial; this.#cell = Cell(undefined as Reactive | undefined, { - description: description.implementation("target"), + description: description?.implementation( + "cell", + "target", + "the storage a mounted reactive" + ), }); this.#value = undefined; this.formula = Formula( () => this.#cell.current?.current ?? this.#initial, - description.implementation("formula") + description?.implementation( + "formula", + "current", + "the current value of the reactive" + ) ); LIFETIME.on.cleanup(this, () => { diff --git a/packages/react/react/src/use-resource.ts b/packages/react/react/src/use-resource.ts index a733ad21..29514e2e 100644 --- a/packages/react/react/src/use-resource.ts +++ b/packages/react/react/src/use-resource.ts @@ -1,7 +1,6 @@ -import { type Description } from "@starbeam/debug"; +import type { Description, Reactive } from "@starbeam/interfaces"; import type { IntoResourceBlueprint } from "@starbeam/resource"; import { LIFETIME } from "@starbeam/runtime"; -import { type Reactive } from "@starbeam/universal"; import { unsafeTrackedElsewhere, useLifecycle, diff --git a/packages/react/react/src/use-setup.ts b/packages/react/react/src/use-setup.ts index 48390d45..29be35f4 100644 --- a/packages/react/react/src/use-setup.ts +++ b/packages/react/react/src/use-setup.ts @@ -1,7 +1,5 @@ -import { callerStack, Desc } from "@starbeam/debug"; -import type { Description } from "@starbeam/interfaces"; -import { isReactive } from "@starbeam/reactive"; -import type { Reactive } from "@starbeam/universal"; +import type { Description, Reactive } from "@starbeam/interfaces"; +import { isReactive, RUNTIME } from "@starbeam/reactive"; import { PolledFormula } from "@starbeam/universal"; import { setupFunction, @@ -47,7 +45,7 @@ export function useSetup< allowMissing: true, }); - const desc = Desc("resource", description); + const desc = RUNTIME.Desc?.("resource", description); const notify = useNotify(); @@ -85,7 +83,10 @@ export function useSetup< ReactiveElement.subscribe(element, reactive); - function compute(props: unknown, caller = callerStack()): unknown { + function compute( + props: unknown, + caller = RUNTIME.callerStack?.() + ): unknown { currentProps = props; return reactive.read(caller); } diff --git a/packages/react/react/src/utils.ts b/packages/react/react/src/utils.ts index 3abeca7c..e8054178 100644 --- a/packages/react/react/src/utils.ts +++ b/packages/react/react/src/utils.ts @@ -1,5 +1,5 @@ -import { Desc, type Description } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; +import type { Description, Reactive } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { UNINITIALIZED } from "@starbeam/shared"; import { Cell } from "@starbeam/universal"; import { useRef } from "react"; @@ -14,12 +14,12 @@ export interface Deps { */ export function useDeps( deps: T, - description?: string | Description + description?: string | Description | undefined ): Deps | undefined { - const desc = Desc("external", description); + const desc = RUNTIME.Desc?.("cell", description, "useDeps"); if (deps?.length) { - const dependencies = deps.map((dep, i) => useProp(dep, desc.index(i))); + const dependencies = deps.map((dep, i) => useProp(dep, desc?.index(i))); return { consume: () => { dependencies.forEach((dep) => dep.read()); @@ -37,7 +37,7 @@ export function useProp( if (ref.current === UNINITIALIZED) { ref.current = Cell(variable, { - description: Desc("external", description), + description: RUNTIME.Desc?.("cell", description, "useProp"), }); } else { ref.current.set(variable); diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index 91fd0192..c00eb084 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -1,13 +1,12 @@ // @vitest-environment jsdom -import { entryPoint } from "@starbeam/debug"; -import reactive from "@starbeam/js"; +import reactive from "@starbeam/collections"; +import type { Reactive } from "@starbeam/interfaces"; import { use, useProp, useReactive, useSetup } from "@starbeam/react"; import { intoReactive } from "@starbeam/reactive"; import { Cell, Formula, - type IntoReactive, Resource, type ResourceBlueprint, } from "@starbeam/universal"; @@ -37,16 +36,14 @@ describe("useResource", () => { ); function send(message: string): void { - entryPoint((): void => { - const latest = Channel.latest(); + const latest = Channel.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - Channel.sendMessage(latest, message); - }); + Channel.sendMessage(latest, message); } let channel = Channel.latest(); @@ -99,16 +96,14 @@ describe("useResource", () => { ); function send(message: string): void { - entryPoint((): void => { - const latest = Channel.latest(); + const latest = Channel.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - Channel.sendMessage(latest, message); - }); + Channel.sendMessage(latest, message); } let channel = Channel.latest(); @@ -166,16 +161,14 @@ describe("useResource", () => { ); function send(message: string): void { - entryPoint((): void => { - const latest = Channel.latest(); + const latest = Channel.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - Channel.sendMessage(latest, message); - }); + Channel.sendMessage(latest, message); } let channel = Channel.latest(); @@ -406,20 +399,18 @@ function SimpleChannel( } function send(message: string): void { - entryPoint((): void => { - const latest = Channel.latest(); + const latest = Channel.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - Channel.sendMessage(latest, message); - }); + Channel.sendMessage(latest, message); } function ChannelResource( - name: IntoReactive + name: string | Reactive ): ResourceBlueprint { const reactive = intoReactive(name); diff --git a/packages/react/react/tests/use-service.spec.ts b/packages/react/react/tests/use-service.spec.ts index 5710e3d3..f4bb702a 100644 --- a/packages/react/react/tests/use-service.spec.ts +++ b/packages/react/react/tests/use-service.spec.ts @@ -1,6 +1,5 @@ // @vitest-environment jsdom -import { callerStack, entryPoint } from "@starbeam/debug"; import { Starbeam, useService } from "@starbeam/react"; import { Cell, Resource } from "@starbeam/universal"; import type { RenderState } from "@starbeam-workspace/react-test-utils"; @@ -65,38 +64,26 @@ describe("services", () => { async function send( message: Auth, - options: { expect: "active" | "inactive" } = { expect: "active" }, - caller = callerStack() + options: { expect: "active" | "inactive" } = { expect: "active" } ): Promise { await result.act(() => { const latest = AUTH_CHANNELS.latest(); if (latest === undefined) { - entryPoint( - () => { - expect(latest, "Channel.latest()").not.toBeUndefined(); - }, - { stack: caller } - ); + expect(latest, "Channel.latest()").not.toBeUndefined(); return; } AUTH_CHANNELS.sendMessage(latest, message); - }, caller); - - entryPoint( - () => { - expect( - channel?.isActive, - `the channel should be ${options.expect}` - ).toBe(options.expect === "active"); - - expect(result.value, "the last rendered auth value").toEqual({ - ...message, - }); - }, - { stack: caller } + }); + + expect(channel?.isActive, `the channel should be ${options.expect}`).toBe( + options.expect === "active" ); + + expect(result.value, "the last rendered auth value").toEqual({ + ...message, + }); } const channel = AUTH_CHANNELS.latest(); diff --git a/packages/react/react/tests/use-setup.spec.ts b/packages/react/react/tests/use-setup.spec.ts index 9d9ca165..5f788e92 100644 --- a/packages/react/react/tests/use-setup.spec.ts +++ b/packages/react/react/tests/use-setup.spec.ts @@ -1,6 +1,5 @@ // @vitest-environment jsdom -import { entryPoint } from "@starbeam/debug"; import type { ReactiveElement } from "@starbeam/react"; import { useReactive, useSetup } from "@starbeam/react"; import { Cell } from "@starbeam/universal"; @@ -64,16 +63,14 @@ describe("useSetup", () => { }); function send(message: string): void { - entryPoint((): void => { - const latest = CHANNELS.latest(); + const latest = CHANNELS.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - CHANNELS.sendMessage(latest, message); - }); + CHANNELS.sendMessage(latest, message); } await result.rerender(); @@ -124,16 +121,14 @@ describe("useSetup", () => { ); function send(message: string): void { - entryPoint((): void => { - const latest = CHANNELS.latest(); + const latest = CHANNELS.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - CHANNELS.sendMessage(latest, message); - }); + CHANNELS.sendMessage(latest, message); } await result.rerender(); @@ -171,16 +166,14 @@ describe("useSetup", () => { }); function send(message: string): void { - entryPoint((): void => { - const latest = CHANNELS.latest(); + const latest = CHANNELS.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - CHANNELS.sendMessage(latest, message); - }); + CHANNELS.sendMessage(latest, message); } await result.rerender(); @@ -234,16 +227,14 @@ describe("useSetup", () => { }); function send(message: string): void { - entryPoint((): void => { - const latest = CHANNELS.latest(); + const latest = CHANNELS.latest(); - if (latest === undefined) { - expect(latest).not.toBeUndefined(); - return; - } + if (latest === undefined) { + expect(latest).not.toBeUndefined(); + return; + } - CHANNELS.sendMessage(latest, message); - }); + CHANNELS.sendMessage(latest, message); } function subscribe(element: ReactiveElement): Cell { diff --git a/packages/react/test-utils/package.json b/packages/react/test-utils/package.json index 9054e3f9..7aba529b 100644 --- a/packages/react/test-utils/package.json +++ b/packages/react/test-utils/package.json @@ -26,6 +26,8 @@ "dependencies": { "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/verify": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^" }, diff --git a/packages/react/test-utils/src/modes.ts b/packages/react/test-utils/src/modes.ts index 0d88a72c..4654f878 100644 --- a/packages/react/test-utils/src/modes.ts +++ b/packages/react/test-utils/src/modes.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { getLast, isPresentArray } from "@starbeam/core-utils"; -import { callerStack, entryPoint, type Stack } from "@starbeam/debug"; import { expect, test, type TestAPI } from "@starbeam-workspace/test-utils"; import * as testing from "@testing-library/react"; import { getByRole, getByText } from "@testing-library/react"; @@ -113,71 +112,55 @@ class RenderResult { return RenderState.getValue(this.#state); } - async rerender( - props?: Props, - caller: Stack = callerStack() - ): Promise> { + async rerender(props?: Props): Promise> { await this.act(() => { this.#rerender(props); - }, caller); + }); - return entryPoint( - () => { - const newProps = props ?? this.#props; + const newProps = props ?? this.#props; - this.#props = newProps; + this.#props = newProps; - SetupTestRoot.assert(this.#setup, this, newProps); + SetupTestRoot.assert(this.#setup, this, newProps); - return this; - }, - { stack: caller } - ); + return this; } - async act( - behavior: () => void, - caller: Stack = callerStack() - ): Promise { + async act(behavior: () => void): Promise { const prev = this.#state.renderCount; act(() => { - entryPoint(behavior, { stack: caller }); + behavior(); }); - await this.rendered(prev, caller); + await this.rendered(prev); } - async rendered(prev: number, caller: Stack = callerStack()): Promise { + async rendered(prev: number): Promise { await testing.waitFor(() => { - entryPoint( - () => { - expect( - this.#state.renderCount, - "expected another render" - ).toBeGreaterThan(prev); - }, - { stack: caller } - ); + () => { + expect( + this.#state.renderCount, + "expected another render" + ).toBeGreaterThan(prev); + }; }); } unmount(): void { - entryPoint(() => { - this.#result.unmount(); - }); + this.#result.unmount(); } find( role: testing.ByRoleMatcher, options?: testing.ByRoleOptions ): TestElement { - return entryPoint(() => this.#element.find(role, options)); + return this.#element.find(role, options); } findByText( id: testing.Matcher, options?: testing.SelectorMatcherOptions ): TestElement { - return entryPoint(() => this.#element.findByText(id, options)); + return this.#element.findByText(id, options); } get innerHTML(): string { @@ -283,15 +266,10 @@ export class SetupTestRoot { } ); - entryPoint( - () => { - SetupTestRoot.assert( - this as unknown as SetupTestRoot, - renderResult, - props as Props - ); - }, - { internal: 1 } + SetupTestRoot.assert( + this as unknown as SetupTestRoot, + renderResult, + props as Props ); return Promise.resolve(renderResult); @@ -365,65 +343,6 @@ type BoundFireObject = { : never; }; -// #region commented1 -// import { entryPoint, UNINITIALIZED } from "@starbeam-workspace/test-utils"; -// import { -// type ByRoleMatcher, -// type ByRoleOptions, -// type FireObject, -// type Matcher, -// type RenderResult as UpstreamRenderResult, -// type SelectorMatcherOptions, -// fireEvent, -// getByRole, -// getByText, -// render, -// } from "@testing-library/react"; -// import { -// type FunctionComponent, -// type ReactElement, -// createElement, -// StrictMode, -// useState, -// } from "react"; -// import { expect, test } from "vitest"; - -// import { TIMELINE } from "../../../../packages/bundle/index.js"; -// import { act } from "./react.js"; - -// // import { UNINITIALIZED } from "../../use-resource/src/utils.js/src/utils.js"; -// // import { entryPoint } from "../../use-resource/tests/support/entry-point.jsce/tests/support/entry-point.js"; -// // import { act } from "../../use-resource/tests/support/react.jsresource/tests/support/react.js"; -// interface RenderResultConfiguration { - -// readonly values: Values; -// readonly rerender: { readonly current: () => void }; -// readonly count: () => number; -// } - -// interface RenderResultOptions extends RenderResultConfiguration { -// readonly props: Props; -// } - -// interface RenderResultState extends RenderResultConfiguration { -// snapshot: RenderSnapshot; -// } - -// interface HtmlTemplate { -// (value: T): string; -// } - -// type BoundFireObject = { -// [P in keyof FireObject]: FireObject[P] extends ( -// // eslint-disable-next-line @typescript-eslint/no-explicit-any -// element: any, -// ...args: infer Args -// ) => infer Return -// ? (...args: Args) => Promise -// : never; -// }; -// #endregion - export class TestElement { static create(element: E): TestElement { return new TestElement(element); diff --git a/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts b/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts index 1dc1e086..af16d528 100644 --- a/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts @@ -1,6 +1,5 @@ // @vitest-environment jsdom -import { entryPoint } from "@starbeam/debug"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; import { useState } from "react"; @@ -609,13 +608,11 @@ class TestResource { } assert(state: string, count: number, id?: number): void { - entryPoint(() => { - expect(this.#state).toBe(state); - expect(this.#count).toBe(count); + expect(this.#state).toBe(state); + expect(this.#count).toBe(count); - if (id) { - expect({ id: this.#id }).toMatchObject({ id }); - } - }); + if (id) { + expect({ id: this.#id }).toMatchObject({ id }); + } } } diff --git a/packages/universal/test-utils/.eslintrc.json b/packages/universal/collections/.eslintrc.json similarity index 72% rename from packages/universal/test-utils/.eslintrc.json rename to packages/universal/collections/.eslintrc.json index 9acee1fa..5bcf281d 100644 --- a/packages/universal/test-utils/.eslintrc.json +++ b/packages/universal/collections/.eslintrc.json @@ -5,7 +5,7 @@ "extends": ["plugin:@starbeam/tight"], "files": ["index.ts", "src/**/*.ts"], "parserOptions": { - "project": "packages/universal/test-utils/tsconfig.json" + "project": "packages/universal/collections/tsconfig.json" } } ] diff --git a/packages/universal/js/.npmrc b/packages/universal/collections/.npmrc similarity index 100% rename from packages/universal/js/.npmrc rename to packages/universal/collections/.npmrc diff --git a/packages/universal/js/CHANGELOG.md b/packages/universal/collections/CHANGELOG.md similarity index 100% rename from packages/universal/js/CHANGELOG.md rename to packages/universal/collections/CHANGELOG.md diff --git a/packages/universal/js/index.ts b/packages/universal/collections/index.ts similarity index 66% rename from packages/universal/js/index.ts rename to packages/universal/collections/index.ts index 343e5b17..e2558747 100644 --- a/packages/universal/js/index.ts +++ b/packages/universal/collections/index.ts @@ -1,4 +1,5 @@ -import { type Description, descriptionFrom } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { Cell } from "@starbeam/universal"; import TrackedArray from "./src/array.js"; @@ -55,14 +56,7 @@ export const reactive = ( reactive.Map = (description?: string | Description): Map => { return ReactiveMap.reactive( Object.is, - descriptionFrom({ - type: "collection:key-value", - api: { - package: "@starbeam/js", - name: "reactive.Map", - }, - fromUser: description, - }) + RUNTIME.Desc?.("collection", description) ); }; @@ -70,44 +64,21 @@ reactive.WeakMap = ( description?: string | Description ): WeakMap => { return TrackedWeakMap.reactive( - descriptionFrom({ - type: "collection:key-value", - api: { - package: "@starbeam/js", - name: "reactive.WeakMap", - }, - fromUser: description, - }) + RUNTIME.Desc?.("collection", description) ); }; reactive.Set = (description?: string | Description): Set => { return ReactiveSet.reactive( Object.is, - descriptionFrom({ - type: "collection:value", - api: { - package: "@starbeam/js", - name: "reactive.Set", - }, - fromUser: description, - }) + RUNTIME.Desc?.("collection", description) ); }; reactive.WeakSet = ( description?: string | Description ): WeakSet => { - return TrackedWeakSet.reactive( - descriptionFrom({ - type: "collection:value", - api: { - package: "@starbeam/js", - name: "reactive.WeakSet", - }, - fromUser: description, - }) - ); + return TrackedWeakSet.reactive(RUNTIME.Desc?.("collection", description)); }; export function object>( @@ -116,14 +87,7 @@ export function object>( description?: string | Description ): T { return TrackedObject.reactive( - descriptionFrom({ - type: "collection:key-value", - api: { - package: "@starbeam/js", - name: "reactive.object", - }, - fromUser: description, - }), + RUNTIME.Desc?.("collection", description), values ); } @@ -132,14 +96,7 @@ reactive.object = object; reactive.array = (values: T[], description?: string | Description): T[] => { return new TrackedArray( - descriptionFrom({ - type: "collection:value", - api: { - package: "@starbeam/js", - name: "reactive.array", - }, - fromUser: description, - }), + RUNTIME.Desc?.("collection", description), values ) as T[]; }; diff --git a/packages/universal/js/package.json b/packages/universal/collections/package.json similarity index 96% rename from packages/universal/js/package.json rename to packages/universal/collections/package.json index 50c8ef45..c2450f19 100644 --- a/packages/universal/js/package.json +++ b/packages/universal/collections/package.json @@ -1,5 +1,5 @@ { - "name": "@starbeam/js", + "name": "@starbeam/collections", "version": "0.8.9", "description": "An implementation of JavaScript builtins built on top of Starbeam reactivity", "type": "module", diff --git a/packages/universal/js/rollup.config.mjs b/packages/universal/collections/rollup.config.mjs similarity index 100% rename from packages/universal/js/rollup.config.mjs rename to packages/universal/collections/rollup.config.mjs diff --git a/packages/universal/js/src/array.ts b/packages/universal/collections/src/array.ts similarity index 88% rename from packages/universal/js/src/array.ts rename to packages/universal/collections/src/array.ts index 21b1203a..bf468e93 100644 --- a/packages/universal/js/src/array.ts +++ b/packages/universal/collections/src/array.ts @@ -6,8 +6,8 @@ // and it will blow up in JS in exactly the same way, so it is safe to assume // that properties within the getter have the correct type in TS. -import { callerStack, type Description } from "@starbeam/debug"; -import type { Stack } from "@starbeam/interfaces"; +import type { CallStack, Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { Collection } from "./collection.js"; @@ -99,7 +99,7 @@ class Shadow { this.#collection = collection; } - at(index: number, caller: Stack): T | undefined { + at(index: number, caller: CallStack | undefined): T | undefined { this.#collection.get( index, index in this.#target ? "hit" : "miss", @@ -116,7 +116,7 @@ class Shadow { if (!fn) { fn = (...args: unknown[]) => { - this.#collection.iterateKeys(callerStack()); + this.#collection.iterateKeys(RUNTIME.callerStack?.()); // eslint-disable-next-line return (this.#target as any)[prop](...args); }; @@ -132,7 +132,7 @@ class Shadow { if (!fn) { fn = (...args: unknown[]) => { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const prev = this.#target.length; // eslint-disable-next-line @@ -167,7 +167,7 @@ class Shadow { return this.#createGetterMethod(name); } - set(prop: PropertyKey, value: unknown, caller: Stack): void { + set(prop: PropertyKey, value: unknown, caller: CallStack | undefined): void { this.#collection.splice(caller); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access (this.#target as UnsafeIndex)[prop] = value; @@ -177,7 +177,7 @@ class Shadow { return this.#createSetterMethod(name); } - updateAt(index: number, value: T, caller: Stack): void { + updateAt(index: number, value: T, caller: CallStack | undefined): void { const current = this.#target[index]; if (Object.is(current, value)) { @@ -190,7 +190,7 @@ class Shadow { this.#target[index] = value; } - updateLength(to: number, caller: Stack): void { + updateLength(to: number, caller: CallStack | undefined): void { // This happens when popping an empty array, for example. if (this.#target.length === to) { return; @@ -202,7 +202,7 @@ class Shadow { // eslint-disable-next-line @typescript-eslint/no-extraneous-class export default class TrackedArray { - constructor(description: Description, arr: T[] = []) { + constructor(description: Description | undefined, arr: T[] = []) { Object.freeze(arr); const target = [...arr]; @@ -210,7 +210,7 @@ export default class TrackedArray { const proxy: T[] = new Proxy(target, { get(getterTarget, prop /*, _receiver */) { if (prop === "length") { - collection.iterateKeys(callerStack()); + collection.iterateKeys(RUNTIME.callerStack?.()); return getterTarget.length; } @@ -219,13 +219,13 @@ export default class TrackedArray { if (index === null) { return shadow.get(prop); } else { - return shadow.at(index, callerStack()); + return shadow.at(index, RUNTIME.callerStack?.()); } }, set(setterTarget, prop, value /*, _receiver */) { const index = convertToInt(prop); - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); if (prop === "length") { shadow.updateLength(value as number, caller); diff --git a/packages/universal/js/src/collection.ts b/packages/universal/collections/src/collection.ts similarity index 77% rename from packages/universal/js/src/collection.ts rename to packages/universal/collections/src/collection.ts index afe3fdc3..90dea33d 100644 --- a/packages/universal/js/src/collection.ts +++ b/packages/universal/collections/src/collection.ts @@ -1,6 +1,6 @@ -import type { Description, Stack } from "@starbeam/debug"; +import type { CallStack, Description } from "@starbeam/interfaces"; import { Cell, Marker } from "@starbeam/reactive"; -import { taggedDescription } from "@starbeam/tags"; +import { getDescription } from "@starbeam/tags"; import { expected, isPresent, verified } from "@starbeam/verify"; class ItemState { @@ -9,24 +9,30 @@ class ItemState { static create( initialized: boolean, - description: Description, + description: Description | undefined, member: string ): ItemState { return new ItemState( Cell(initialized, { description: description - .key(member) - .asImplementation({ reason: "initialization tracking" }), + ?.implementation("cell", "initialization", "initialization tracking") + .key(member), }), - Marker({ description: description.key(member) }) + Marker({ description: description?.key(member) }) ); } - static initialized(description: Description, member: string): ItemState { + static initialized( + description: Description | undefined, + member: string + ): ItemState { return ItemState.create(true, description, member); } - static uninitialized(description: Description, member: string): ItemState { + static uninitialized( + description: Description | undefined, + member: string + ): ItemState { return ItemState.create(false, description, member); } @@ -35,11 +41,11 @@ class ItemState { this.#value = value; } - check(caller: Stack): void { + check(caller: CallStack | undefined): void { this.#present.read(caller); } - delete(caller: Stack): void { + delete(caller: CallStack | undefined): void { this.#present.set(false, caller); } @@ -47,12 +53,12 @@ class ItemState { this.#present.current = true; } - read(caller: Stack): void { + read(caller: CallStack | undefined): void { this.#present.read(caller); this.#value.read(caller); } - update(caller: Stack): void { + update(caller: CallStack | undefined): void { this.#present.current = true; this.#value.mark(caller); } @@ -61,7 +67,10 @@ class ItemState { class Item { #value: ItemState; - static initialized(description: Description, member: string): Item { + static initialized( + description: Description | undefined, + member: string + ): Item { // If an item is initialized for the first time with a value, that means // that no consumer attempted to read the value before, so there's nothing // to do (other than update the iteration of the entire collection). @@ -69,9 +78,9 @@ class Item { } static uninitialized( - description: Description, + description: Description | undefined, member: string, - caller: Stack + caller: CallStack | undefined ): Item { const item = new Item(ItemState.uninitialized(description, member)); @@ -86,35 +95,38 @@ class Item { this.#value = value; } - check(caller: Stack): void { + check(caller: CallStack | undefined): void { this.#value.check(caller); } - delete(caller: Stack): void { + delete(caller: CallStack | undefined): void { this.#value.delete(caller); } - read(caller: Stack): void { + read(caller: CallStack | undefined): void { this.#value.read(caller); } - set(caller: Stack): void { + set(caller: CallStack | undefined): void { this.#value.update(caller); } } export class Collection { - #description: Description; + #description: Description | undefined; #items: Map; #iteration: Marker | undefined; static #objects = new WeakMap>(); - static create(description: Description, object: object): Collection { + static create( + description: Description | undefined, + object: object + ): Collection { const collection = new Collection( undefined, new Map(), - description.key("entries") + description?.key("entries") ); Collection.#objects.set(object, collection); return collection; @@ -133,7 +145,7 @@ export class Collection { constructor( iteration: undefined, items: Map, - description: Description + description: Description | undefined ) { this.#description = description; this.#iteration = iteration; @@ -144,7 +156,7 @@ export class Collection { key: K, disposition: "hit" | "miss", description: string, - caller: Stack + caller: CallStack | undefined ): void { let item = this.#items.get(key); @@ -159,7 +171,7 @@ export class Collection { item.check(caller); } - delete(key: K, caller: Stack): void { + delete(key: K, caller: CallStack | undefined): void { const item = this.#items.get(key); // if there's no item with that key, that means that no consumer read from @@ -181,7 +193,7 @@ export class Collection { key: K, disposition: "hit" | "miss", description: string, - caller: Stack + caller: CallStack | undefined ): void { let item = this.#items.get(key); @@ -196,14 +208,14 @@ export class Collection { key: K, disposition: "hit" | "miss", member: string, - caller: Stack + caller: CallStack | undefined ): Item { if (this.#iteration === undefined) { this.#iteration = Marker({ description: this.#description }); } let item: Item; - const iteration = taggedDescription(this.#iteration); + const iteration = getDescription(this.#iteration); if (disposition === "miss") { item = Item.uninitialized(iteration, member, caller); @@ -215,7 +227,7 @@ export class Collection { return item; } - iterateKeys(caller: Stack): void { + iterateKeys(caller: CallStack | undefined): void { if (this.#iteration === undefined) { this.#iteration = Marker({ description: this.#description }); } @@ -229,7 +241,7 @@ export class Collection { key: K, disposition: "key:stable" | "key:changes", description: string, - caller: Stack + caller: CallStack | undefined ): void { if (disposition === "key:changes") { this.splice(caller); @@ -249,7 +261,7 @@ export class Collection { } } - splice(caller: Stack): void { + splice(caller: CallStack | undefined): void { if (this.#iteration === undefined) { // if nobody has iterated this collection, nobody will care that it was modified return; diff --git a/packages/universal/js/src/decorator.ts b/packages/universal/collections/src/decorator.ts similarity index 100% rename from packages/universal/js/src/decorator.ts rename to packages/universal/collections/src/decorator.ts diff --git a/packages/universal/js/src/iterable.ts b/packages/universal/collections/src/iterable.ts similarity index 75% rename from packages/universal/js/src/iterable.ts rename to packages/universal/collections/src/iterable.ts index 52073e04..ef8007f5 100644 --- a/packages/universal/js/src/iterable.ts +++ b/packages/universal/collections/src/iterable.ts @@ -1,6 +1,5 @@ -import type { Stack } from "@starbeam/debug"; -import { callerStack, type Description } from "@starbeam/debug"; -import { Cell, type Equality, Marker } from "@starbeam/reactive"; +import type { CallStack, Description } from "@starbeam/interfaces"; +import { Cell, type Equality, Marker, RUNTIME } from "@starbeam/reactive"; import { UNINITIALIZED } from "@starbeam/shared"; class Entry { @@ -9,7 +8,7 @@ class Entry { static initialized( value: V, - desc: Description, + desc: Description | undefined, equality: Equality ): Entry { return new Entry( @@ -18,23 +17,30 @@ class Entry { equals: equals(equality), }), Cell(true, { - description: desc.implementation("initialized", { - reason: "initialized", - }), + description: desc?.implementation( + "cell", + "initialized?", + "the entry was initialized" + ), }) ); } - static uninitialized(desc: Description, equality: Equality): Entry { + static uninitialized( + desc: Description | undefined, + equality: Equality + ): Entry { return new Entry( Cell(UNINITIALIZED, { description: desc, equals: equals(equality), }), Cell(false, { - description: desc.implementation("initialized", { - reason: "initialized", - }), + description: desc?.implementation( + "cell", + "initialized?", + "the entry was initialized" + ), }) ); } @@ -44,7 +50,7 @@ class Entry { this.#initialized = initialized; } - delete(caller: Stack): "deleted" | "unchanged" { + delete(caller: CallStack | undefined): "deleted" | "unchanged" { const cell = this.#value.read(caller); if (cell === UNINITIALIZED) { @@ -56,7 +62,7 @@ class Entry { } } - get(caller: Stack): V | undefined { + get(caller: CallStack | undefined): V | undefined { const current = this.#value.read(caller); if (current === UNINITIALIZED) { @@ -66,11 +72,14 @@ class Entry { } } - isPresent(caller: Stack): boolean { + isPresent(caller: CallStack | undefined): boolean { return this.#initialized.read(caller); } - set(value: V, caller: Stack): "initialized" | "updated" | "unchanged" { + set( + value: V, + caller: CallStack | undefined + ): "initialized" | "updated" | "unchanged" { if (this.#value.read(caller) === UNINITIALIZED) { this.#value.set(value, caller); this.#initialized.set(true, caller); @@ -96,7 +105,7 @@ const EXTRA_CALLER_FRAME = 1; export class ReactiveMap implements Map { readonly [Symbol.toStringTag] = "Map"; - readonly #description: Description; + readonly #description: Description | undefined; readonly #entries = new Map>(); readonly #equality: Equality; readonly #keys: Marker; @@ -104,20 +113,23 @@ export class ReactiveMap implements Map { static reactive( equality: Equality, - description: Description + description: Description | undefined ): ReactiveMap { return new ReactiveMap(description, equality); } - private constructor(description: Description, equality: Equality) { + private constructor( + description: Description | undefined, + equality: Equality + ) { this.#description = description; this.#equality = equality; - this.#keys = Marker({ description: description.key("keys") }); - this.#values = Marker({ description: description.key("values") }); + this.#keys = Marker({ description: description?.key("keys") }); + this.#values = Marker({ description: description?.key("values") }); } get size(): number { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#keys.read(caller); let size = 0; @@ -136,7 +148,7 @@ export class ReactiveMap implements Map { } clear(): void { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); if (this.#entries.size > EMPTY_MAP_SIZE) { this.#entries.clear(); this.#keys.mark(caller); @@ -145,7 +157,7 @@ export class ReactiveMap implements Map { } delete(key: K): boolean { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const entry = this.#entries.get(key); if (entry) { @@ -163,7 +175,7 @@ export class ReactiveMap implements Map { } *entries(): IterableIterator<[K, V]> { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#keys.read(caller); this.#values.read(caller); @@ -177,7 +189,7 @@ export class ReactiveMap implements Map { if (entry === undefined) { entry = Entry.uninitialized( - this.#description.key( + this.#description?.key( typeof key === "string" || typeof key === "number" ? String(key) : "entry" @@ -194,7 +206,7 @@ export class ReactiveMap implements Map { callbackfn: (value: V, key: K, map: Map) => void, thisArg?: unknown ): void { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#keys.read(caller); this.#values.read(caller); @@ -204,17 +216,17 @@ export class ReactiveMap implements Map { } get(key: K): V | undefined { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const entry = this.#entry(key); return entry.get(caller); } has(key: K): boolean { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); return this.#entry(key).isPresent(caller); } - *#iterate(caller: Stack): IterableIterator<[K, Entry]> { + *#iterate(caller: CallStack | undefined): IterableIterator<[K, Entry]> { for (const [key, entry] of this.#entries) { if (entry.isPresent(caller)) { yield [key, entry]; @@ -223,7 +235,7 @@ export class ReactiveMap implements Map { } *keys(): IterableIterator { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#keys.read(caller); for (const [key] of this.#iterate(caller)) { @@ -232,7 +244,7 @@ export class ReactiveMap implements Map { } set(key: K, value: V): this { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const entry = this.#entry(key); const disposition = entry.set(value, caller); @@ -250,7 +262,7 @@ export class ReactiveMap implements Map { *values(): IterableIterator { // add an extra frame for the internal JS call to .next() - const caller = callerStack(EXTRA_CALLER_FRAME); + const caller = RUNTIME.callerStack?.(EXTRA_CALLER_FRAME); this.#values.read(caller); @@ -263,26 +275,29 @@ export class ReactiveMap implements Map { export class ReactiveSet implements Set { readonly [Symbol.toStringTag] = "Set"; - readonly #description: Description; + readonly #description: Description | undefined; readonly #entries = new Map>(); readonly #equality: Equality; readonly #values: Marker; static reactive( equality: Equality, - description: Description + description: Description | undefined ): ReactiveSet { return new ReactiveSet(description, equality); } - private constructor(description: Description, equality: Equality) { + private constructor( + description: Description | undefined, + equality: Equality + ) { this.#description = description; this.#equality = equality; - this.#values = Marker({ description: description.key("values") }); + this.#values = Marker({ description: description?.key("values") }); } get size(): number { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#values.read(caller); @@ -300,7 +315,7 @@ export class ReactiveSet implements Set { } add(value: T): this { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const entry = this.#entry(value); @@ -314,7 +329,7 @@ export class ReactiveSet implements Set { } clear(): void { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); if (this.#entries.size > EMPTY_MAP_SIZE) { this.#entries.clear(); @@ -323,7 +338,7 @@ export class ReactiveSet implements Set { } delete(value: T): boolean { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const entry = this.#entries.get(value); @@ -341,7 +356,7 @@ export class ReactiveSet implements Set { } *entries(): IterableIterator<[T, T]> { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#values.read(caller); @@ -354,7 +369,7 @@ export class ReactiveSet implements Set { callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: unknown ): void { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#values.read(caller); @@ -364,12 +379,12 @@ export class ReactiveSet implements Set { } has(value: T): boolean { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); return this.#entry(value).isPresent(caller); } - *#iterate(caller: Stack): IterableIterator<[T, Entry]> { + *#iterate(caller: CallStack | undefined): IterableIterator<[T, Entry]> { for (const [value, entry] of this.#entries) { if (entry.isPresent(caller)) { yield [value, entry]; @@ -378,7 +393,7 @@ export class ReactiveSet implements Set { } *keys(): IterableIterator { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#values.read(caller); diff --git a/packages/universal/js/src/map.ts b/packages/universal/collections/src/map.ts similarity index 71% rename from packages/universal/js/src/map.ts rename to packages/universal/collections/src/map.ts index 848f5bfe..9d746f2c 100644 --- a/packages/universal/js/src/map.ts +++ b/packages/universal/collections/src/map.ts @@ -1,6 +1,5 @@ -import type { Stack } from "@starbeam/debug"; -import { callerStack, type Description } from "@starbeam/debug"; -import { type Equality, Marker } from "@starbeam/reactive"; +import type { CallStack, Description } from "@starbeam/interfaces"; +import { type Equality, Marker, RUNTIME } from "@starbeam/reactive"; interface Entry { has: Marker; @@ -11,21 +10,21 @@ export class TrackedWeakMap implements WeakMap { static reactive( - description: Description + description: Description | undefined ): WeakMap { return new TrackedWeakMap(description) as WeakMap; } - readonly #description: Description; + readonly #description: Description | undefined; readonly #iteration: Marker; readonly #storage: WeakMap; readonly #vals: WeakMap; readonly #equals: Equality = Object.is; - private constructor(description: Description) { + private constructor(description: Description | undefined) { this.#vals = new WeakMap(); - this.#iteration = Marker(description.detail("iterate")); + this.#iteration = Marker(description?.detail("collection", "iterate")); this.#storage = new WeakMap(); this.#description = description; @@ -36,8 +35,12 @@ export class TrackedWeakMap if (markers === undefined) { markers = { - get: Marker(this.#description.key(describeKey(key)).detail("get")), - has: Marker(this.#description.key(describeKey(key)).detail("has")), + get: Marker( + this.#description?.key(describeKey(key)).detail("cell", "get") + ), + has: Marker( + this.#description?.key(describeKey(key)).detail("cell", "has") + ), }; this.#storage.set(key, markers); } @@ -49,36 +52,44 @@ export class TrackedWeakMap return this.#storage.get(key); } - #get(key: K, caller: Stack, entry: Entry = this.#entry(key)): V | undefined { + #get( + key: K, + caller: CallStack | undefined, + entry: Entry = this.#entry(key) + ): V | undefined { entry.get.read(caller); return this.#vals.get(key); } get(key: K): V | undefined { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const entry = this.#entry(key); return this.#has(key, caller, entry) ? this.#get(key, caller, entry) : undefined; } - #has(key: K, caller: Stack, entry: Entry = this.#entry(key)): boolean { + #has( + key: K, + caller: CallStack | undefined, + entry: Entry = this.#entry(key) + ): boolean { entry.has.read(caller); return this.#vals.has(key); } has(key: K): boolean { - return this.#has(key, callerStack()); + return this.#has(key, RUNTIME.callerStack?.()); } - #insert(key: K, caller: Stack): void { + #insert(key: K, caller: CallStack | undefined): void { const entry = this.#tryEntry(key); if (entry) entry.has.mark(caller); this.#iteration.mark(caller); } - #update(key: K, caller: Stack): void { + #update(key: K, caller: CallStack | undefined): void { const entry = this.#tryEntry(key); if (entry) entry.get.mark(caller); @@ -86,7 +97,7 @@ export class TrackedWeakMap } set(key: K, value: V): this { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); // intentionally avoid consuming the `has` or `get` markers while setting. const has = this.#vals.has(key); @@ -103,7 +114,7 @@ export class TrackedWeakMap return this; } - #delete(key: K, caller: Stack): void { + #delete(key: K, caller: CallStack | undefined): void { const entry = this.#tryEntry(key); // if anyone checked the presence of this key before, invalidate the check. @@ -114,7 +125,7 @@ export class TrackedWeakMap } delete(key: K): boolean { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); // if the key is not in the map, then deleting it has no reactive effect. if (this.#vals.has(key)) { diff --git a/packages/universal/js/src/mapper.ts b/packages/universal/collections/src/mapper.ts similarity index 100% rename from packages/universal/js/src/mapper.ts rename to packages/universal/collections/src/mapper.ts diff --git a/packages/universal/js/src/object.ts b/packages/universal/collections/src/object.ts similarity index 91% rename from packages/universal/js/src/object.ts rename to packages/universal/collections/src/object.ts index ce341082..1a6de369 100644 --- a/packages/universal/js/src/object.ts +++ b/packages/universal/collections/src/object.ts @@ -1,15 +1,18 @@ -import { callerStack, type Description } from "@starbeam/debug"; -import type { Stack } from "@starbeam/interfaces"; +import type { CallStack, Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { Collection } from "./collection.js"; // eslint-disable-next-line @typescript-eslint/no-extraneous-class export default class TrackedObject { - static reactive(description: Description, obj: T): T { + static reactive( + description: Description | undefined, + obj: T + ): T { return new TrackedObject(description, obj) as T; } - private constructor(description: Description, obj: object) { + private constructor(description: Description | undefined, obj: object) { // copy the properties from the object to the proxy, but preserve getters and setters const target = Object.create(Reflect.getPrototypeOf(obj)) as object; @@ -22,7 +25,7 @@ export default class TrackedObject { const proxy = new Proxy(target, { defineProperty(_, key, descriptor) { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); define(key, descriptor, caller); return true; @@ -30,7 +33,7 @@ export default class TrackedObject { deleteProperty(_, prop) { if (Reflect.has(target, prop)) { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); collection.delete(prop, caller); Reflect.deleteProperty(target, prop); @@ -40,7 +43,7 @@ export default class TrackedObject { }, get(_, prop, _receiver) { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); collection.get( prop, @@ -52,7 +55,7 @@ export default class TrackedObject { }, getOwnPropertyDescriptor(_, prop) { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); collection.get( prop, @@ -68,7 +71,7 @@ export default class TrackedObject { }, has(_, prop) { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const has = Reflect.has(target, prop); collection.check(prop, has ? "hit" : "miss", member(prop), caller); @@ -80,7 +83,7 @@ export default class TrackedObject { }, ownKeys() { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); collection.iterateKeys(caller); return Reflect.ownKeys(target); @@ -91,7 +94,7 @@ export default class TrackedObject { }, set(_: object, prop: PropertyKey, value: unknown, _receiver) { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const descriptor = Reflect.getOwnPropertyDescriptor(target, prop); @@ -123,7 +126,7 @@ export default class TrackedObject { function define( key: PropertyKey, descriptor: PropertyDescriptor, - caller: Stack + caller: CallStack | undefined ): boolean { const updates = Descriptor.updates(target, key, descriptor); diff --git a/packages/universal/js/src/set.ts b/packages/universal/collections/src/set.ts similarity index 76% rename from packages/universal/js/src/set.ts rename to packages/universal/collections/src/set.ts index 6ff68c8f..f94b4adf 100644 --- a/packages/universal/js/src/set.ts +++ b/packages/universal/collections/src/set.ts @@ -1,22 +1,23 @@ -import { callerStack, type Description } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { Collection } from "./collection.js"; export class TrackedWeakSet implements WeakSet { - static reactive(description: Description): TrackedWeakSet { + static reactive(description: Description | undefined): TrackedWeakSet { return new TrackedWeakSet(description); } readonly #collection: Collection; readonly #vals: WeakSet; - private constructor(description: Description) { + private constructor(description: Description | undefined) { this.#collection = Collection.create(description, this); this.#vals = new WeakSet(); } has(value: T): boolean { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const has = this.#vals.has(value); @@ -32,7 +33,7 @@ export class TrackedWeakSet implements WeakSet { return this; } - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#vals.add(value); this.#collection.set(value, "key:changes", " {value}", caller); @@ -48,7 +49,7 @@ export class TrackedWeakSet implements WeakSet { return false; } - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); this.#collection.delete(value, caller); return this.#vals.delete(value); diff --git a/packages/universal/js/tests/.eslintrc.json b/packages/universal/collections/tests/.eslintrc.json similarity index 68% rename from packages/universal/js/tests/.eslintrc.json rename to packages/universal/collections/tests/.eslintrc.json index cc310792..c73531c3 100644 --- a/packages/universal/js/tests/.eslintrc.json +++ b/packages/universal/collections/tests/.eslintrc.json @@ -5,7 +5,7 @@ "extends": ["plugin:@starbeam/loose"], "files": ["**/*.ts"], "parserOptions": { - "project": "packages/universal/js/tests/tsconfig.json" + "project": "packages/universal/collections/tests/tsconfig.json" } } ] diff --git a/packages/universal/js/tests/.npmrc b/packages/universal/collections/tests/.npmrc similarity index 100% rename from packages/universal/js/tests/.npmrc rename to packages/universal/collections/tests/.npmrc diff --git a/packages/universal/js/tests/CHANGELOG.md b/packages/universal/collections/tests/CHANGELOG.md similarity index 100% rename from packages/universal/js/tests/CHANGELOG.md rename to packages/universal/collections/tests/CHANGELOG.md diff --git a/packages/universal/js/tests/array.spec.ts b/packages/universal/collections/tests/array.spec.ts similarity index 98% rename from packages/universal/js/tests/array.spec.ts rename to packages/universal/collections/tests/array.spec.ts index 21d05e7c..a92280f0 100644 --- a/packages/universal/js/tests/array.spec.ts +++ b/packages/universal/collections/tests/array.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { Formula } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/js/tests/map.spec.ts b/packages/universal/collections/tests/map.spec.ts similarity index 99% rename from packages/universal/js/tests/map.spec.ts rename to packages/universal/collections/tests/map.spec.ts index 4240b0a1..8d8d1f0d 100644 --- a/packages/universal/js/tests/map.spec.ts +++ b/packages/universal/collections/tests/map.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { describe, expect, test } from "vitest"; import { Invalidation } from "./support.js"; diff --git a/packages/universal/js/tests/object.spec.ts b/packages/universal/collections/tests/object.spec.ts similarity index 99% rename from packages/universal/js/tests/object.spec.ts rename to packages/universal/collections/tests/object.spec.ts index b2879fac..b1dee0d6 100644 --- a/packages/universal/js/tests/object.spec.ts +++ b/packages/universal/collections/tests/object.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { Formula } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/js/tests/package.json b/packages/universal/collections/tests/package.json similarity index 73% rename from packages/universal/js/tests/package.json rename to packages/universal/collections/tests/package.json index 9a266f48..174fb5ee 100644 --- a/packages/universal/js/tests/package.json +++ b/packages/universal/collections/tests/package.json @@ -1,6 +1,6 @@ { "private": true, - "name": "@starbeam-tests/js", + "name": "@starbeam-tests/collections", "version": "1.0.0", "type": "module", "starbeam:type": "tests", @@ -9,7 +9,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/universal": "workspace:^" } } diff --git a/packages/universal/js/tests/set.spec.ts b/packages/universal/collections/tests/set.spec.ts similarity index 98% rename from packages/universal/js/tests/set.spec.ts rename to packages/universal/collections/tests/set.spec.ts index 382c1459..07140b28 100644 --- a/packages/universal/js/tests/set.spec.ts +++ b/packages/universal/collections/tests/set.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { Formula } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/js/tests/support.ts b/packages/universal/collections/tests/support.ts similarity index 100% rename from packages/universal/js/tests/support.ts rename to packages/universal/collections/tests/support.ts diff --git a/packages/universal/js/tests/tsconfig.json b/packages/universal/collections/tests/tsconfig.json similarity index 100% rename from packages/universal/js/tests/tsconfig.json rename to packages/universal/collections/tests/tsconfig.json diff --git a/packages/universal/js/tests/weak-map.spec.ts b/packages/universal/collections/tests/weak-map.spec.ts similarity index 98% rename from packages/universal/js/tests/weak-map.spec.ts rename to packages/universal/collections/tests/weak-map.spec.ts index 8c21c631..8fbcfafb 100644 --- a/packages/universal/js/tests/weak-map.spec.ts +++ b/packages/universal/collections/tests/weak-map.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { CachedFormula } from "@starbeam/reactive"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/js/tests/weak-set.spec.ts b/packages/universal/collections/tests/weak-set.spec.ts similarity index 96% rename from packages/universal/js/tests/weak-set.spec.ts rename to packages/universal/collections/tests/weak-set.spec.ts index 333002fc..f4adfd7b 100644 --- a/packages/universal/js/tests/weak-set.spec.ts +++ b/packages/universal/collections/tests/weak-set.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { describe, expect, test } from "vitest"; import { Invalidation } from "./support.js"; diff --git a/packages/universal/js/tsconfig.json b/packages/universal/collections/tsconfig.json similarity index 100% rename from packages/universal/js/tsconfig.json rename to packages/universal/collections/tsconfig.json diff --git a/packages/universal/core-utils/index.ts b/packages/universal/core-utils/index.ts index 38377552..b34fcb33 100644 --- a/packages/universal/core-utils/index.ts +++ b/packages/universal/core-utils/index.ts @@ -8,8 +8,13 @@ export { isEmptyArray, isPresentArray, isSingleItemArray, - mapOrNullifyEmpty, + mapArray, + mapIfPresent, + mapPresentArray, + type MutablePresentArray, nullifyEmptyArray, + type PresentArray, + type ReadonlyPresentArray, removeItem, removeItemAt, withoutFirst, @@ -17,6 +22,18 @@ export { zipArrays, } from "./src/array.js"; export { type UnknownFn } from "./src/function.js"; +export { + DisplayStruct, + type DisplayStructOptions, +} from "./src/inspect/display-struct.js"; +export { + DEBUG, + DEBUG_NAME, + INSPECT, + type Inspect, + inspect, + inspector, +} from "./src/inspect/inspect-support.js"; export { iterableHasItems, reverse } from "./src/iterable.js"; export type { JsonArray, @@ -26,6 +43,10 @@ export type { } from "./src/json.js"; export { isJSONObject, stringifyJSON } from "./src/json.js"; export { + dataGetter, + def, + defineObject, + defMethod, getter, isObject, method, diff --git a/packages/universal/core-utils/src/array.ts b/packages/universal/core-utils/src/array.ts index ca1ba314..cada17b9 100644 --- a/packages/universal/core-utils/src/array.ts +++ b/packages/universal/core-utils/src/array.ts @@ -17,12 +17,34 @@ export function isPresentArray< return list && list.length > EMPTY_LENGTH; } -export function mapOrNullifyEmpty( +export function mapArray( + list: PresentArray, + mapper: (item: T, index: number) => U +): MutablePresentArray; +export function mapArray( + list: T[] | readonly T[], + mapper: (item: T, index: number) => U +): U[]; +export function mapArray( + list: T[] | readonly T[] | PresentArray, + mapper: (item: T, index: number) => U +): U[] | PresentArray { + return list.map(mapper); +} + +export function mapPresentArray( + list: PresentArray, + mapper: (item: T, index: number) => U +): PresentArray { + return list.map(mapper) as PresentArray; +} + +export function mapIfPresent( list: T[] | readonly T[] | undefined | null, mapper: (item: T, index: number) => U -): U[] | undefined { +): PresentArray | undefined { if (list && isPresentArray(list)) { - return list.map(mapper); + return mapPresentArray(list, mapper); } else { return; } diff --git a/packages/universal/debug/src/inspect/display-struct.ts b/packages/universal/core-utils/src/inspect/display-struct.ts similarity index 100% rename from packages/universal/debug/src/inspect/display-struct.ts rename to packages/universal/core-utils/src/inspect/display-struct.ts diff --git a/packages/universal/debug/src/inspect/inspect-support.ts b/packages/universal/core-utils/src/inspect/inspect-support.ts similarity index 97% rename from packages/universal/debug/src/inspect/inspect-support.ts rename to packages/universal/core-utils/src/inspect/inspect-support.ts index 6af3ca7f..88a248d5 100644 --- a/packages/universal/debug/src/inspect/inspect-support.ts +++ b/packages/universal/core-utils/src/inspect/inspect-support.ts @@ -1,4 +1,3 @@ -import { isObject } from "@starbeam/verify"; import type { CustomInspectFunction, InspectOptionsStylized, @@ -6,9 +5,9 @@ import type { } from "util"; import { + DisplayStruct, type DisplayStructOptions, type Fields, - DisplayStruct, } from "./display-struct.js"; export const INSPECT = Symbol.for("nodejs.util.inspect.custom"); @@ -93,7 +92,7 @@ export function inspect( value: unknown, ...args: Parameters ): unknown { - if (isObject(value)) { + if (typeof value === "object" && value !== null) { return (value as Partial)[INSPECT]?.(...args); } else { return value; diff --git a/packages/universal/debug/src/inspect/json-value.ts b/packages/universal/core-utils/src/inspect/json-value.ts similarity index 100% rename from packages/universal/debug/src/inspect/json-value.ts rename to packages/universal/core-utils/src/inspect/json-value.ts diff --git a/packages/universal/core-utils/src/object.ts b/packages/universal/core-utils/src/object.ts index 221aab3e..93fe7a43 100644 --- a/packages/universal/core-utils/src/object.ts +++ b/packages/universal/core-utils/src/object.ts @@ -1,6 +1,4 @@ -import { getFirst } from "./array.js"; -import { isSingleItemArray } from "./array.js"; -import { isPresentArray } from "./array.js"; +import { getFirst, isPresentArray, isSingleItemArray } from "./array.js"; export function isObject(value: unknown): value is object { return typeof value === "object" && value !== null; @@ -36,17 +34,33 @@ type Define = Expand< } >; -export function method( +export function method(fn: T[K] & AnyFunction): T; +export function method( + fn: V +): Define; +export function method(fn: AnyFunction): TypedPropertyDescriptor { + return { + enumerable: false, + configurable: true, + writable: false, + value: fn, + }; +} +export function defMethod( object: T, key: K, fn: T[K] & AnyFunction ): T; -export function method( +export function defMethod( object: T, key: K, fn: V ): Define; -export function method(object: object, key: AnyKey, fn: AnyFunction): object { +export function defMethod( + object: object, + key: AnyKey, + fn: AnyFunction +): object { Object.defineProperty(object, key, { enumerable: false, configurable: true, @@ -83,10 +97,37 @@ export function getter( return object; } +type DefinedObject>> = + Expand<{ + [P in keyof R]: R[P] extends TypedPropertyDescriptor ? V : unknown; + }>; + +export function defineObject< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + R extends Record> +>(properties: R): DefinedObject { + return Object.defineProperties({}, properties) as DefinedObject; +} + +export function dataGetter(getter: () => T): TypedPropertyDescriptor { + return { + get: getter, + enumerable: true, + }; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function def>>( + object: T, + properties: R +): T & DefinedObject { + return Object.defineProperties(object, properties) as T & DefinedObject; +} + export function readonly( object: T, key: K, - ...args: [] | [T[K]] + ...args: [] | [T[K]] | [() => T[K]] ): WithReadonly; export function readonly( object: T, diff --git a/packages/universal/debug/index.ts b/packages/universal/debug/index.ts index e8868b71..2a499b51 100644 --- a/packages/universal/debug/index.ts +++ b/packages/universal/debug/index.ts @@ -1,68 +1,5 @@ import "./src/setup.js"; -import { descriptionFrom } from "./src/stack.js"; - -export { Description, REUSE_ID } from "./src/description/impl.js"; -export { - DisplayStruct, - type DisplayStructOptions, -} from "./src/inspect/display-struct.js"; -export { - DEBUG, - DEBUG_NAME, - INSPECT, - type Inspect, - inspect, - inspector, -} from "./src/inspect/inspect-support.js"; -export { logged } from "./src/logged.js"; -export { LOGGER, type Logger, LogLevel } from "./src/logger.js"; -export { - Block, - Fragment, - Message, - Style, - Styled, - Styles, -} from "./src/message.js"; -export { describeModule, type DisplayParts } from "./src/module.js"; -export { - callerStack, - Desc, - descriptionFrom, - entryPoint, - entryPointFn, - entryPoints, - idFrom, - isErrorWithStack, - Stack, -} from "./src/stack.js"; +export { default as debugRuntime } from "./src/debug.js"; export { debugTag, logTag } from "./src/tag.js"; -export { - type CellConsumeOperation, - type CellUpdateOperation, - type DebugFilter, - type DebugListener, - type DebugOperation, - DebugTimeline, - type Flush, - type FrameConsumeOperation, - type MutationLog, -} from "./src/timeline.js"; export { Tree } from "./src/tree.js"; -export type { - ApiDetails, - DescriptionArgs, - DescriptionDetails, - DescriptionParts, - DescriptionType, - DetailDescription, - DetailsPart, - MemberDescription, -} from "@starbeam/interfaces"; - -export const defaultDescription = descriptionFrom({ - id: NaN, - type: "erased", - api: "anonymous", -}); diff --git a/packages/universal/debug/package.json b/packages/universal/debug/package.json index 7dada9fb..82ae203b 100644 --- a/packages/universal/debug/package.json +++ b/packages/universal/debug/package.json @@ -39,7 +39,9 @@ "@domtree/flavors": "workspace:^", "@starbeam/core-utils": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/shared": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/verify": "workspace:^", "ansicolor": "^1.1.100", "buffer": "^6.0.3", diff --git a/packages/universal/debug/src/call-stack/debug/index.ts b/packages/universal/debug/src/call-stack/debug/index.ts new file mode 100644 index 00000000..7cf040d8 --- /dev/null +++ b/packages/universal/debug/src/call-stack/debug/index.ts @@ -0,0 +1,3 @@ +import { callerStack } from "./stack.js"; + +export default callerStack; diff --git a/packages/universal/debug/src/call-stack/debug/module.ts b/packages/universal/debug/src/call-stack/debug/module.ts new file mode 100644 index 00000000..aeb6b42a --- /dev/null +++ b/packages/universal/debug/src/call-stack/debug/module.ts @@ -0,0 +1,125 @@ +import { firstNItems } from "@starbeam/core-utils"; + +const _SOURCE_PARTS = + /^(?![a-z]+:)(?:(?@[^/\\]+)[/])?(?[^/\\]+)(?:[/\\](?.*))?$/; + +const _RELATIVE_MODULE = /^\.{1,2}\//; + +export function parseModule(filename: string, codebase?: string): ParsedModule { + return normalizeModule(filename, codebase); + + // FIXME:: Do we want/need to support package inference? If so, how should it work? + + // if (RELATIVE_MODULE.exec(filename)) + + // const groups = SOURCE_PARTS.exec(filename)?.groups; + + // if (groups === undefined) return normalizeModule(filename, codebase); + + // return { + // root: { + // type: "package", + // scope: groups["scope"], + // name: verified(groups["name"], isPresent), + // }, + // path: verified(groups["path"], isPresent), + // }; +} + +export interface ParsedModule { + root?: string | { package: string } | undefined; + path: string; +} + +export function normalizeModule( + filename: string, + codebase?: string | undefined +): ParsedModule { + const path = normalizePath(filename); + + if (codebase) { + const { prefix, suffix } = pivotPath(codebase, path); + console.log({ codebase, path, prefix, suffix }); + return { + root: prefix, + path: stripLeadingSlash(suffix), + }; + } + + return { path }; +} + +function stripLeadingSlash(path: string) { + return path.startsWith("/") ? path.slice("/".length) : path; +} + +/** + * The whole `Stack` system is only intended to be used for logging, so the + * edge-cases where this normalization wouldn't work (verbatim paths on Windows) + * shouldn't matter. + */ +function normalizePath(...pathParts: (string | null | undefined)[]): string { + return pathParts + .filter((part): part is string => typeof part === "string") + .map((p: string) => p.replaceAll(/[\\]/g, "/")) + .join("/"); +} + +/** + * This function takes two paths and returns the suffix of the target that comes + * after any shared prefix with the source. + * + * For example, if the source is `/src/app/foo/bar` and the target is + * `/src/app/baz/qux`, this function will return `baz/qux`. + */ +export function pivotPath( + source: string, + target: string +): { prefix: string; suffix: string } { + const sourceParts = source.split("/"); + const targetParts = target.split("/"); + + const pivotIndex = sourceParts.findIndex((part, index) => { + return part !== targetParts[index]; + }); + + return { + prefix: firstNItems(sourceParts, pivotIndex).join("/") + "/", + suffix: targetParts.slice(pivotIndex).join("/"), + }; +} + +if (import.meta.vitest) { + const { test, expect } = import.meta.vitest; + + test("should return the path if it's not nested in a root", () => { + expect(normalizeModule("./foo/bar")).toStrictEqual({ + path: "./foo/bar", + }); + expect(parseModule("./foo/bar")).toStrictEqual({ + path: "./foo/bar", + }); + }); + + test("should find the pivot path", () => { + expect( + normalizeModule("/src/app/index.ts", "/src/app/some/nested/file.ts") + ).toStrictEqual({ + root: "/src/app/", + path: "index.ts", + }); + expect( + parseModule("/src/app/index.ts", "/src/app/some/nested/file.ts") + ).toStrictEqual({ + root: "/src/app/", + path: "index.ts", + }); + }); + + test("pivotPath", () => { + expect(pivotPath("/src/app/foo/bar", "/src/app/baz/qux")).toEqual({ + prefix: "/src/app/", + suffix: "baz/qux", + }); + }); +} diff --git a/packages/universal/debug/src/call-stack/debug/stack.ts b/packages/universal/debug/src/call-stack/debug/stack.ts new file mode 100644 index 00000000..466c3ec6 --- /dev/null +++ b/packages/universal/debug/src/call-stack/debug/stack.ts @@ -0,0 +1,228 @@ +import { + dataGetter, + defineObject, + firstNItems, + getFirst, + isPresent, + isPresentArray, + mapArray, + type PresentArray, +} from "@starbeam/core-utils"; +import type { CallStack, StackFrame } from "@starbeam/interfaces"; +import { hasType, verified, verify } from "@starbeam/verify"; +import StackTracey from "stacktracey"; + +import { parseModule } from "./module.js"; + +const INITIAL_INTERNAL_FRAMES = 1; +const CALLER = 1; + +export function callerStack( + internal = INITIAL_INTERNAL_FRAMES +): CallStack | undefined { + const ErrorClass = Error; + + if ("captureStackTrace" in ErrorClass) { + const err = {} as { stack: string }; + ErrorClass.captureStackTrace(err, callerStack); + return callStack(err.stack)?.slice(internal); + } else { + const stack = Error( + "An error created in the internals of Stack.create" + ).stack; + + verify(stack, hasType("string")); + return callStack(stack)?.slice(internal + CALLER); + } +} + +function callStack(stack: string, nearby?: string): CallStack | undefined { + const parsed = parseStack(stack); + + if (parsed === undefined) { + return undefined; + } + + const { header, entries, lines, trace } = parsed; + + const frames = mapArray(entries, (entry) => + stackFrame(() => trace.withSource(entry), nearby) + ); + + return { + header, + frames, + slice: (n: number) => { + const stack = lines.slice(n).join("\n"); + return callStack(`${header}\n${stack}`, nearby); + }, + }; +} + +function stackFrame( + reify: () => StackTracey.Entry, + nearby: string | undefined +): StackFrame { + let reified: StackTracey.Entry | null = null; + + function getEntry(): StackTracey.Entry { + if (!reified) reified = reify(); + return reified; + } + + return defineObject({ + action: dataGetter(() => getEntry().callee), + module: dataGetter(() => parseModule(getEntry().file, nearby)), + loc: dataGetter(() => { + const entry = getEntry(); + + if (entry.line === undefined) return undefined; + + return { + line: entry.line, + column: entry.column, + }; + }), + }); +} + +const MISSING = -1; + +interface ParsedStack { + readonly header: string; + readonly entries: PresentArray; + readonly lines: PresentArray; + readonly trace: StackTracey; +} + +function parseStack(stack: string): ParsedStack | undefined { + const trace = new StackTracey(stack); + + if (!isPresentArray(trace.items)) return undefined; + + const [firstFrame] = trace.items; + + const first = firstFrame.beforeParse; + const lines = stack.split("\n"); + + const offset = lines.findIndex((line) => line.trim() === first); + + if (offset === MISSING) { + throw Error( + `An assumption was incorrect: A line that came from StackTracey cannot be found in the original trace.\n\n== Stack ==\n\n${stack}\n\n== Line ==\n\n${first}` + ); + } + + const header = firstNItems(lines, offset).join("\n"); + const rest = lines.slice(offset); + + if (!isPresentArray(rest)) return undefined; + + return { + header, + entries: trace.items, + lines: rest, + trace, + }; +} + +function isErrorWithStack(value: unknown): value is Error & { stack: string } { + return hasType("object")(value) && hasType("string")((value as Error).stack); +} + +if (import.meta.vitest) { + const { test, expect, describe } = import.meta.vitest; + const filename = new URL(import.meta.url).pathname; + + function anAction() { + throw Error(ERROR_MESSAGE); + } + + const ERROR_LOC = { + line: 138, + column: 11, + }; + + function aCallerAction() { + return callerStack(); + } + + const ERROR_MESSAGE = "an error happened in an action"; + const CALLER_FRAME = 1; + + test("parseStack", () => { + try { + anAction(); + } catch (e) { + const { header, entries, lines, trace } = verified( + parseStack(verified(e, isErrorWithStack).stack), + isPresent + ); + + expect(header).toBe(`Error: ${ERROR_MESSAGE}`); + expect(lines).toHaveLength(entries.length); + expect(trace.items).toEqual(entries); + expect(getFirst(lines)).toMatch(/\banAction\b/); + } + }); + + { + function testCallStack() { + try { + anAction(); + } catch (e) { + const stack = verified( + callStack(verified(e, isErrorWithStack).stack, filename), + isPresent + ); + + expect(stack.header).toBe(`Error: ${ERROR_MESSAGE}`); + const frameSize = stack.frames.length; + expect(stack.slice(CALLER_FRAME)?.frames).toHaveLength( + frameSize - CALLER_FRAME + ); + + const firstFrame = getFirst(stack.slice(CALLER_FRAME)?.frames ?? []); + expect(firstFrame?.action).toBe(TEST_NAME); + } + } + + const TEST_NAME = testCallStack.name; + + test("callStack", testCallStack); + } + + { + function testCallerStack() { + const caller = verified(aCallerAction(), isPresent); + + expect(getFirst(caller.frames).action).toBe(TEST_NAME); + } + + const TEST_NAME = testCallerStack.name; + + test("callerStack", testCallerStack); + } + + describe("StackFrame", () => { + test("action", () => { + try { + anAction(); + } catch (e) { + verify(e, isErrorWithStack); + + const trace = new StackTracey(e.stack); + const first = verified(getFirst(trace.items), isPresent); + + const frame = stackFrame(() => trace.withSource(first), filename); + + expect(frame.action).toBe("anAction"); + expect(frame.module).toEqual({ + path: "stack.ts", + root: new URL(".", import.meta.url).pathname, + }); + expect(frame.loc).toEqual(ERROR_LOC); + } + }); + }); +} diff --git a/packages/universal/debug/src/call-stack/prod.ts b/packages/universal/debug/src/call-stack/prod.ts new file mode 100644 index 00000000..f4dd1545 --- /dev/null +++ b/packages/universal/debug/src/call-stack/prod.ts @@ -0,0 +1,3 @@ +import type { DebugRuntime } from "@starbeam/interfaces"; + +export default (() => undefined) satisfies DebugRuntime["callerStack"]; diff --git a/packages/universal/debug/src/component/stack.ts b/packages/universal/debug/src/component/stack.ts deleted file mode 100644 index 770bd58d..00000000 --- a/packages/universal/debug/src/component/stack.ts +++ /dev/null @@ -1,180 +0,0 @@ -import type { anydom } from "@domtree/flavors"; -import type * as interfaces from "@starbeam/interfaces"; - -export interface DebugTree { - app: (description: interfaces.Description) => App; - route: (description: interfaces.Description) => Route; - component: (description: interfaces.Description) => Component; - snapshot: () => interfaces.RootNode; -} - -export interface App { - route: (description: interfaces.Description) => Route; - component: (description: interfaces.Description) => Component; -} - -export interface Route { - component: (description: interfaces.Description) => Component; -} - -export interface Component { - component: (description: interfaces.Description) => Component; - lifecycle: (timing: "layout" | "idle") => Lifecycle; - ref: (description: interfaces.Description) => Ref; - modifier: (timing: "layout" | "idle") => Modifier; - resource: (reactive: interfaces.Tagged) => interfaces.Unsubscribe; - domResource: ( - timing: "layout" | "idle", - reactive: interfaces.Tagged - ) => interfaces.Unsubscribe; -} - -export interface Lifecycle { - setup: ( - timing: "layout" | "idle", - protocol: interfaces.Tagged - ) => interfaces.Unsubscribe; -} - -export interface Ref { - element: (element: anydom.Element | null) => interfaces.Unsubscribe; -} - -// intentionally empty for now -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface Modifier {} - -let PickedDebugTree: DebugTree; - -if (import.meta.env.DEV) { - class RootNode { - #children: ChildNode[] = []; - #description?: interfaces.Description; - } - - class AppNode implements App { - #children: ChildNode[] = []; - #description: interfaces.Description; - - constructor(description: interfaces.Description) { - this.#description = description; - } - - component(_description: interfaces.Description): Component { - throw new Error("Method not implemented."); - } - - route(_description: interfaces.Description): Route { - throw new Error("Method not implemented."); - } - } - - class DebugTreeImpl implements DebugTree { - #app: AppNode | null = null; - #root: RootNode = new RootNode(); - - app(description: interfaces.Description): App { - if (!this.#app) { - this.#app = new AppNode(description); - } - return this.#app; - } - - component(_description: interfaces.Description): Component { - throw new Error("Method not implemented."); - } - - route(_description: interfaces.Description): Route { - throw new Error("Method not implemented."); - } - - snapshot(): interfaces.RootNode { - throw new Error("Method not implemented."); - } - } - - // eslint-disable-next-line unused-imports/no-unused-vars - class ComponentImpl implements Component { - #children: interfaces.ComponentNode[] = []; - #delegate: ChildDelegate; - #parts: interfaces.ComponentNode[] = []; - - constructor(delegate: ChildDelegate) { - this.#delegate = delegate; - } - - component(_description: interfaces.Description): Component { - throw new Error("Method not implemented."); - } - domResource( - _timing: "layout" | "idle", - _reactive: interfaces.Tagged - ): interfaces.Unsubscribe { - throw new Error("Method not implemented."); - } - lifecycle(_timing: "layout" | "idle"): Lifecycle { - throw new Error("Method not implemented."); - } - modifier(_timing: "layout" | "idle"): Modifier { - throw new Error("Method not implemented."); - } - ref(_description: interfaces.Description): Ref { - throw new Error("Method not implemented."); - } - resource(_reactive: interfaces.Tagged): interfaces.Unsubscribe { - throw new Error("Method not implemented."); - } - } - - interface ChildDelegate { - addChild: (child: ChildNode) => interfaces.Unsubscribe; - } - - PickedDebugTree = new DebugTreeImpl(); -} else { - const NOOP_UNSUBSCRIBE = (): void => { - /* noop */ - }; - - const EMPTY_ROOT: interfaces.EmptyRoot = { - type: "empty", - }; - - const NOOP_PROD_TREE: DebugTree = { - app: (): App => NOOP_APP, - route: (): Route => NOOP_ROUTE, - component: (): Component => NOOP_COMPONENT, - snapshot: () => EMPTY_ROOT, - }; - - const NOOP_APP: App = { - route: (): Route => NOOP_ROUTE, - component: (): Component => NOOP_COMPONENT, - }; - - const NOOP_ROUTE: Route = { - component: (): Component => NOOP_COMPONENT, - }; - - const NOOP_COMPONENT: Component = { - component: (): Component => NOOP_COMPONENT, - lifecycle: (): Lifecycle => NOOP_LIFECYCLE, - ref: (): Ref => NOOP_REF, - modifier: (): Modifier => NOOP_MODIFIER, - resource: (): interfaces.Unsubscribe => NOOP_UNSUBSCRIBE, - domResource: (): interfaces.Unsubscribe => NOOP_UNSUBSCRIBE, - }; - const NOOP_LIFECYCLE: Lifecycle = { - setup: (): interfaces.Unsubscribe => NOOP_UNSUBSCRIBE, - }; - - const NOOP_REF: Ref = { - element: (): interfaces.Unsubscribe => NOOP_UNSUBSCRIBE, - }; - - const NOOP_MODIFIER: Modifier = {}; - - PickedDebugTree = NOOP_PROD_TREE; -} - -export const DebugTree = PickedDebugTree; diff --git a/packages/universal/debug/src/debug.ts b/packages/universal/debug/src/debug.ts new file mode 100644 index 00000000..43b96acb --- /dev/null +++ b/packages/universal/debug/src/debug.ts @@ -0,0 +1,22 @@ +import type { DebugRuntime } from "@starbeam/interfaces"; + +import callerStack from "./call-stack/debug/index.js"; +import { + describe, + describeTagged, + getUserFacing, +} from "./description/debug/describe.js"; +import desc from "./description/debug/index.js"; + +const untrackedReadBarrier = (() => { + /* FIXME: do nothing for now */ +}) satisfies DebugRuntime["untrackedReadBarrier"]; + +export default { + desc, + callerStack, + getUserFacing, + untrackedReadBarrier, + describe, + describeTagged, +} satisfies DebugRuntime; diff --git a/packages/universal/debug/src/description/README.md b/packages/universal/debug/src/description/README.md index ef461606..f28a5e51 100644 --- a/packages/universal/debug/src/description/README.md +++ b/packages/universal/debug/src/description/README.md @@ -1,3 +1,7 @@ +> This document is outdaated but reflects some early thinking about the +> description architecture. It's still useful as a way to drive future design +> work, and should be updated as the design evolves. + # The Description Architecture The goal of the description architecture is to provide a way to describe reactive operations in a way that is both human readable and easy to use in a debug tool. diff --git a/packages/universal/debug/src/description/debug/describe.ts b/packages/universal/debug/src/description/debug/describe.ts new file mode 100644 index 00000000..be3aa7ae --- /dev/null +++ b/packages/universal/debug/src/description/debug/describe.ts @@ -0,0 +1,385 @@ +import { isPresentArray } from "@starbeam/core-utils"; +import type { + ChildType, + DebugRuntime, + DescriptionDetails, + Nesting, + ReactiveId, + ReactiveType, + Tagged, +} from "@starbeam/interfaces"; +import { getID } from "@starbeam/shared"; +import { getDescription } from "@starbeam/tags"; + +export type FullName = Flat | [Flat, ...ChildType[]]; + +export function describeTagged(tagged: Tagged): string { + const description = getDescription(tagged)?.details; + return description ? describe(description) : `{unknown reactive value}`; +} + +export function describe(description: DescriptionDetails): string { + return describeFullName(getFullName(description)); +} + +export function getFullName(description: DescriptionDetails): FullName { + const base = getBase(description); + + if (base.type === "specified" || base.type === "anonymous") { + return base; + } + + let parent = base.parent; + const path: Nesting[] = [base]; + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + while (true) { + const next = getBase(parent); + + if (next.type === "specified" || next.type === "anonymous") { + return [next, ...path.reverse()]; + } else { + path.push(next); + parent = next.parent; + } + } +} + +interface Specified { + readonly type: "specified"; + readonly value: string; +} + +interface Anonymous { + readonly type: "anonymous"; + readonly id: ReactiveId; + readonly kind: ReactiveType; +} + +type Flat = Specified | Anonymous; + +export function describeFullName(fullName: FullName): string { + if (Array.isArray(fullName)) { + const accum = []; + + for (const part of fullName) { + switch (part.type) { + case "specified": + case "anonymous": + accum.push(describeFlat(part)); + break; + default: + accum.push(describeNesting(part)); + } + } + + return accum.join(""); + } else { + return describeFlat(fullName); + } +} + +function describeFlat(fullName: Flat): string { + if (fullName.type === "specified") { + return fullName.value; + } else { + return `{anonymous ${fullName.kind}:${getIdString(fullName.id)}}`; + } +} + +function describeNesting(nesting: ChildType): string { + switch (nesting.type) { + case "property": + return `.${nesting.value}`; + case "index": + return `[${nesting.value}]`; + case "implementation": + return `->{impl: ${nesting.value.name}}`; + case "detail": { + const { name, args } = nesting.value; + + return isPresentArray(args) + ? `->${name}(${args.join(", ")})` + : `->${name}`; + } + case "key": { + const { name } = nesting.value; + + return `.get(${name})`; + } + } +} + +function getBase(description: DescriptionDetails): Nesting | Flat { + if (description.specified) { + return { type: "specified", value: description.specified }; + } else if (description.nesting) { + return description.nesting; + } else { + return { type: "anonymous", kind: description.type, id: description.id }; + } +} + +function getIdString(id: ReactiveId, accum = "", nested = false): string { + switch (typeof id) { + case "string": + case "number": { + if (accum === "" || accum.endsWith("(")) { + accum += String(id); + } else if (accum.endsWith(")")) { + accum += `->${id}`; + } else { + accum += `/${id}`; + } + break; + } + + default: { + if (accum !== "") accum += "->"; + if (nested) accum += "("; + + for (const part of id) { + accum = getIdString(part, accum, true); + } + + if (nested) accum += ")"; + } + } + + return accum; +} + +export const getUserFacing = (( + description: D +): D => { + if (description?.nesting?.type === "implementation") { + return getUserFacing(description.nesting.parent) as D; + } else { + return description; + } +}) satisfies DebugRuntime["getUserFacing"]; + +if (import.meta.vitest) { + const { test, expect, describe: group } = import.meta.vitest; + + test("getIdString", () => { + expect(getIdString("myid")).toEqual("myid"); + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + expect(getIdString(123)).toEqual("123"); + expect(getIdString(["a", "b", "c"])).toEqual("a/b/c"); + expect(getIdString(["a", ["b", "c"], "d"])).toEqual("a->(b/c)->d"); + expect(getIdString(["a", ["b", "c"], ["d", "e"]])).toEqual( + "a->(b/c)->(d/e)" + ); + expect( + getIdString([ + ["a", "b"], + ["c", "d"], + ]) + ).toEqual("(a/b)->(c/d)"); + expect(getIdString(["a", ["b", "c"], ["d", "e"], "f"])).toEqual( + "a->(b/c)->(d/e)->f" + ); + expect(getIdString(["a", ["b", "c"], ["d", "e"], ["f", "g"]])).toEqual( + "a->(b/c)->(d/e)->(f/g)" + ); + // multiple levels of nesting + expect(getIdString(["a", ["b", ["c", "d"], "e"], "f"])).toEqual( + "a->(b->(c/d)->e)->f" + ); + }); + + test("getUserFacing", () => { + const parentId = getID(); + const childId = getID(); + + const parent = { + type: "cell", + caller: undefined, + id: parentId, + specified: "mycell", + } satisfies DescriptionDetails; + + const child = { + type: "cell", + caller: undefined, + id: childId, + nesting: { + type: "implementation", + parent, + value: { name: "initialized?", reason: "the cell was initialized" }, + }, + } satisfies DescriptionDetails; + + expect(getUserFacing(child)).toEqual(parent); + expect(getUserFacing(parent)).toEqual(parent); + }); + + test("describeFlat", () => { + expect(describeFlat({ type: "specified", value: "mycell" })).toEqual( + "mycell" + ); + const id = getID(); + expect( + describeFlat({ + type: "anonymous", + kind: "cell", + id, + }) + ).toEqual(`{anonymous cell:${id}}`); + }); + + test("describeFullName", () => { + expect(describeFullName({ type: "specified", value: "mycell" })).toEqual( + "mycell" + ); + const id = getID(); + expect( + describeFullName({ + type: "anonymous", + kind: "cell", + id, + }) + ).toEqual(`{anonymous cell:${id}}`); + + const parentId = getID(); + const childId = getID(); + + const parent = { + type: "cell", + caller: undefined, + id: parentId, + specified: "mycell", + } satisfies DescriptionDetails; + + const child = { + type: "cell", + caller: undefined, + id: childId, + nesting: { + type: "implementation", + parent, + value: { + name: "initialized?", + reason: "the cell was initialized", + }, + }, + } satisfies DescriptionDetails; + + expect(describeFullName(getFullName(child))).toEqual( + "mycell->{impl: initialized?}" + ); + expect( + describeFullName([ + { type: "specified", value: "mycell" }, + { type: "implementation", value: { name: "initialized?", reason: "" } }, + ]) + ).toEqual("mycell->{impl: initialized?}"); + + const specified = { + type: "specified", + value: "mycell", + } satisfies Specified; + + const anonymous = { + type: "anonymous", + kind: "cell", + id: 1, + } satisfies Anonymous; + + expect(describeFullName([anonymous, { type: "index", value: 2 }])).toEqual( + "{anonymous cell:1}[2]" + ); + expect(describeFullName([specified, { type: "index", value: 2 }])).toEqual( + "mycell[2]" + ); + + expect( + describeFullName([ + anonymous, + { type: "key", value: { name: "foo", key: {} } }, + ]) + ).toEqual("{anonymous cell:1}.get(foo)"); + + expect( + describeFullName([ + specified, + { type: "key", value: { name: "foo", key: {} } }, + ]) + ).toEqual("mycell.get(foo)"); + + expect( + describeFullName([anonymous, { type: "property", value: "foo" }]) + ).toEqual("{anonymous cell:1}.foo"); + + expect( + describeFullName([specified, { type: "property", value: "foo" }]) + ).toEqual("mycell.foo"); + }); + + group("getFullName", () => { + test("anonymous", () => { + const id = getID(); + const description = { + type: "cell", + caller: undefined, + id, + } satisfies DescriptionDetails; + + expect(getFullName(description)).toEqual({ + type: "anonymous", + kind: "cell", + id, + } satisfies Anonymous); + }); + + test("specified", () => { + const description = { + type: "cell", + caller: undefined, + id: getID(), + specified: "mycell", + } satisfies DescriptionDetails; + + expect(getFullName(description)).toEqual({ + type: "specified", + value: "mycell", + } satisfies Specified); + }); + + test("nested", () => { + const parentId = getID(); + const childId = getID(); + + const parent = { + type: "collection", + caller: undefined, + id: parentId, + specified: "mymap", + } satisfies DescriptionDetails; + + const child = { + type: "collection:item", + caller: undefined, + id: childId, + nesting: { + type: "key", + parent, + value: { name: "foo", key: "foo" }, + } satisfies Extract, + } satisfies DescriptionDetails; + + expect(getFullName(child)).toEqual([ + { + type: "specified", + value: "mymap", + } satisfies Specified, + { + type: "key", + parent, + value: { name: "foo", key: "foo" }, + } satisfies Nesting, + ]); + }); + }); +} diff --git a/packages/universal/debug/src/description/debug/description.ts b/packages/universal/debug/src/description/debug/description.ts new file mode 100644 index 00000000..f437e12b --- /dev/null +++ b/packages/universal/debug/src/description/debug/description.ts @@ -0,0 +1,145 @@ +import { getFirst, isObject } from "@starbeam/core-utils"; +import type { + Api, + CallStack, + DescriptionRuntime, + ReactiveId, +} from "@starbeam/interfaces"; +import type * as interfaces from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; +import { getID } from "@starbeam/shared"; + +export class Description implements interfaces.Description { + readonly #details: interfaces.DescriptionDetails; + + constructor(desc: interfaces.DescriptionDetails) { + this.#details = desc; + } + + get details(): interfaces.DescriptionDetails { + return this.#details; + } + + get type(): interfaces.ReactiveType { + return this.#details.type; + } + + get caller(): CallStack | undefined { + return this.#details.caller; + } + + get frame(): interfaces.StackFrame | undefined { + return getFirst(this.caller?.frames ?? []); + } + + get id(): ReactiveId { + return this.#details.id; + } + + get isAnonymous(): boolean { + return this.#details.specified === undefined; + } + + index(index: number, caller?: CallStack | undefined): interfaces.Description { + return new Description({ + type: "collection:item", + id: this.#extendId(index), + nesting: { type: "index", parent: this, value: index }, + caller: caller ?? this.#details.caller, + }); + } + + property( + name: string, + caller?: CallStack | undefined + ): interfaces.Description { + return new Description({ + type: "collection:item", + id: this.#extendId(name), + nesting: { type: "property", parent: this, value: name }, + caller: caller ?? this.#details.caller, + }); + } + + key( + key: { name: string; key: unknown } | string | number, + caller?: CallStack | undefined + ): interfaces.Description { + const value: { name: string; key: unknown } = isObject(key) + ? { name: key.name, key: key.key } + : { name: String(key), key }; + + return new Description({ + type: "collection:item", + id: this.#extendId(value.name), + nesting: { type: "key", parent: this, value }, + caller: caller ?? this.#details.caller, + }); + } + + detail( + type: interfaces.ReactiveType, + name: string, + args: string[] | CallStack = [], + caller?: CallStack | undefined + ): interfaces.Description { + const info = Array.isArray(args) + ? { args, caller } + : { args: [], caller: args }; + + return new Description({ + type, + id: this.#extendId(name), + nesting: { + type: "detail", + parent: this, + value: { name, args: info.args }, + }, + caller: info.caller ?? this.#details.caller, + }); + } + + implementation( + type: interfaces.ReactiveType, + name: string, + reason: string, + caller?: CallStack | undefined + ): interfaces.Description { + return new Description({ + type, + id: this.#extendId(name), + nesting: { + type: "implementation", + parent: this, + value: { name, reason }, + }, + caller: caller ?? this.#details.caller, + }); + } + + #extendId(id: ReactiveId): ReactiveId { + return Array.isArray(this.id) ? [...this.id, id] : [this.id, id]; + } +} + +const DESC_FRAME = 1; + +export const Desc = (( + type: interfaces.ReactiveType, + specified: string | interfaces.Description | undefined, + api: string | Api | undefined +): interfaces.Description => { + if (isObject(specified)) return specified; + + const caller = RUNTIME.callerStack?.(DESC_FRAME); + api = api ?? caller?.frames[0].action; + const id = getID(); + + return new Description({ + type, + id, + api: typeof api === "string" ? { type: "simple", name: api, caller } : api, + specified, + caller, + }); +}) satisfies DescriptionRuntime; diff --git a/packages/universal/debug/src/description/debug/index.ts b/packages/universal/debug/src/description/debug/index.ts new file mode 100644 index 00000000..ccb44dff --- /dev/null +++ b/packages/universal/debug/src/description/debug/index.ts @@ -0,0 +1,4 @@ +import type { DescriptionRuntime } from "@starbeam/interfaces"; + +import { Desc as desc } from "./description.js"; +export default desc satisfies DescriptionRuntime; diff --git a/packages/universal/debug/src/description/impl.ts b/packages/universal/debug/src/description/impl.ts deleted file mode 100644 index 86c7c946..00000000 --- a/packages/universal/debug/src/description/impl.ts +++ /dev/null @@ -1,651 +0,0 @@ -import type * as interfaces from "@starbeam/interfaces"; -import { getID } from "@starbeam/shared"; -import { exhaustive, expected, isEqual, verify } from "@starbeam/verify"; -import ansicolor, { type Color } from "ansicolor"; - -import { DisplayStruct } from "../inspect/display-struct.js"; -import { DisplayParts } from "../module.js"; -import { callerStack, type Stack } from "../stack.js"; - -/** - * This symbol is used in APIs that accept an ID to indicate that an existing ID should be reused. - * This value should never be used as an ID. - */ -export const REUSE_ID = Symbol.for("starbeam.id:reuse"); -export type REUSE_ID = typeof REUSE_ID; - -/** - * This symbol is used in production mode to indicate that there is no description available. This - * value should never be used as an ID. - */ -export const ERASED_ID = Symbol.for("starbeam.id:erased"); -export type ERASED_ID = typeof ERASED_ID; - -let PickedDescription: DescriptionStatics; - -export interface DescriptionStatics { - is: (description: unknown) => description is interfaces.Description; - from: (args: interfaces.DescriptionArgs) => interfaces.Description; -} - -if (import.meta.env.DEV) { - function stylize(color: Color, text: string, shouldColor: boolean): string { - return shouldColor ? color(text) : text; - } - - class DebugDescription - implements interfaces.Description, interfaces.DescriptionArgs - { - /** - * The {@linkcode DescriptionArgs.api} is the user-facing, public API entry point that the developer used to - * construct the thing that this description is describing. For example, the `useSetup` hook in - * `@starbeam/react` has the type "resource" and the api "useStarbeam". - */ - readonly #api: string | interfaces.ApiDetails | undefined; - /** - * Optional additional details, provided by the end user. The `DescriptionDetails` may represent a - * part of a parent description (see {@linkcode MemberDescription}, - * {@linkcode MethodDescription}). In those cases, they are still rooted in end-user supplied - * description details . - */ - readonly #details: interfaces.DescriptionDetails | undefined; - - readonly #id: interfaces.ReactiveId; - - #internal: - | { - reason?: string | undefined; - userFacing: Description; - } - | undefined; - - #stack?: Stack | undefined; - - /** - * The type is a high-level categorization from the perspective of Starbeam. It is used in - * developer tools to decide how to render the description. - */ - readonly #type: interfaces.DescriptionType; - - static from(args: interfaces.DescriptionArgs): interfaces.Description { - if (DebugDescription.is(args)) { - return args; - } else if (DebugDescription.is(args.fromUser)) { - return args.fromUser; - } - - return new DebugDescription( - args.id ?? getID(), - args.type, - args.api, - args.fromUser, - args.internal, - args.stack - ) as Description; - } - - static is(description: unknown): description is interfaces.Description { - return !!(description && description instanceof DebugDescription); - } - - constructor( - id: interfaces.ReactiveId, - type: interfaces.DescriptionType, - api: string | interfaces.ApiDetails | undefined, - details: interfaces.DescriptionDetails | undefined, - internal: - | { reason?: string | undefined; userFacing: Description } - | undefined, - stack: Stack | undefined - ) { - this.#id = id; - this.#type = type; - this.#api = api; - this.#details = details; - this.#internal = internal; - this.#stack = stack; - } - - get api(): string | interfaces.ApiDetails | undefined { - return this.#api ?? this.#parent?.api; - } - - get #apiPart(): interfaces.ApiDetails | undefined { - if (typeof this.#api === "string") { - return { - name: this.#api, - }; - } else { - return this.#api; - } - } - - get #detailsPart(): interfaces.DetailsPart { - if (typeof this.#details === "string") { - return { type: "value", name: this.#details }; - } else if (this.#details === undefined) { - return { type: "anonymous" }; - } else { - return this.#details; - } - } - - get frame(): interfaces.StackFrame | undefined { - return this.#stack?.caller; - } - - #fromUser(shouldColor: boolean): string { - if (this.#details) { - if (typeof this.#details === "string") { - return this.#details; - } else { - switch (this.#details.type) { - case "member": - switch (this.#details.kind) { - case "index": - return `[${this.#details.name}]`; - case "property": - return `.${this.#details.name}`; - case "key": { - return `->${this.#details.name}`; - } - } - - case "detail": { - const detail = stylize( - ansicolor.dim, - `->${this.#details.name}`, - shouldColor - ); - - if (this.#details.args) { - return `${detail}(${this.#details.args - .map((a) => stylize(ansicolor.magenta, a, shouldColor)) - .join(", ")})`; - } else { - return detail; - } - } - - case "method": - return `.${this.#details.name}()`; - - default: - exhaustive(this.#details); - } - } - } else { - return `{anonymous ${this.type}}`; - } - } - - get fromUser(): string { - return this.#fromUser(true); - } - - get name(): string { - if (this.#details !== undefined) { - if (typeof this.#details === "string") { - return this.#details; - } else { - return this.#fromUser(false); - } - } else { - return `{${this.#idName}:anonymous ${this.type}}`; - } - } - - #fullName(shouldColor: boolean): string { - if (this.#details !== undefined) { - if (typeof this.#details === "string") { - return this.#details; - } else { - return `${this.#details.parent.#fullName( - shouldColor - )}${this.#fromUser(shouldColor)}`; - } - } else { - return `{${this.#idName}:anonymous ${this.type}}`; - } - } - - get fullName(): string { - return this.#fullName(false); - } - - get id(): interfaces.ReactiveId { - return this.#id; - } - - get #idName(): string { - if (typeof this.#id === "string" || typeof this.#id === "number") { - return String(this.#id); - } else { - return this.#id.map(String).join("/"); - } - } - - get isAnonymous(): boolean { - return this.#details === undefined; - } - - get #parent(): interfaces.Description | undefined { - if (typeof this.#details === "object") { - return this.#details.parent; - } - } - - get parts(): interfaces.DescriptionParts { - return { - type: this.#type, - id: this.#id, - api: this.#apiPart, - details: this.#detailsPart, - userFacing: this.#userFacingDesc, - frame: this.#stack?.caller, - stack: this.#stack?.stack, - internal: this.#internal, - }; - } - - get type(): interfaces.DescriptionType { - return this.#type; - } - - get userFacing(): interfaces.Description { - if (this.#internal) { - return this.#internal.userFacing; - } else { - return this as interfaces.Description; - } - } - get #userFacingDesc(): interfaces.Description { - return (this.#internal?.userFacing ?? this) as interfaces.Description; - } - - [Symbol.for("nodejs.util.inspect.custom")](): object { - return DisplayStruct("Description", { - id: this.#id, - type: this.#type, - api: this.#api, - details: this.#details, - internal: this.#internal, - stack: this.#stack, - }); - } - - asImplementation(options?: { reason: string }): interfaces.Description { - return new DebugDescription( - this.#id, - this.#type, - this.#api, - this.#details, - { - reason: options?.reason, - userFacing: this.#parent ?? this, - }, - this.#stack - ); - } - - forApi(api: string | interfaces.ApiDetails): interfaces.Description { - return new DebugDescription( - this.#id, - this.#type, - api, - this.#details, - this.#internal, - this.#stack - ); - } - - #caller(options?: interfaces.DescriptionDescribeOptions): string { - const caller = this.#stack?.caller; - - if (caller !== undefined) { - return caller.display(options); - } else { - return ""; - } - } - - describe(options: interfaces.DescriptionDescribeOptions = {}): string { - const name = this.#name(options); - const color = options.color ?? true; - - if (this.#internal) { - const desc = stylize( - ansicolor.dim, - this.#internal.reason ? `[${this.#internal.reason}]` : "[internals]", - color - ); - return `${name} ${desc}`; - } else { - return name; - } - } - - detail( - this: DebugDescription, - name: string, - args?: - | string[] - | { args?: string[]; note?: string; id?: interfaces.ReactiveId } - ): interfaces.Description { - let detailArgs: string[] | undefined; - let note: string | undefined; - let id: interfaces.ReactiveId; - - if (Array.isArray(args)) { - detailArgs = args; - id = this.#extendId(name); - } else if (args) { - detailArgs = args.args; - note = args.note; - id = this.#extendId(args.id ?? name); - } else { - id = this.#extendId(name); - } - - return new DebugDescription( - id, - "formula", - this.#api, - { - type: "detail", - parent: this, - name, - args: detailArgs, - note, - }, - undefined, - this.#stack - ); - } - - #extendId(id: interfaces.ReactiveId | REUSE_ID): interfaces.ReactiveId { - if (id === REUSE_ID) { - return this.#id; - } else if (Array.isArray(this.#id)) { - return [...this.#id, id]; - } else { - return [this.#id, id]; - } - } - - implementation( - id: interfaces.ReactiveId | symbol, - details?: { - reason?: string; - userFacing?: interfaces.Description; - stack?: Stack; - } - ): DebugDescription { - if (typeof id === "symbol") { - verify( - id, - isEqual(REUSE_ID), - expected("symbol passed to implementation()").toBe("REUSE_ID") - ); - } - - return new DebugDescription( - this.#extendId(id), - this.#type, - this.#api, - this.#details, - { - reason: details?.reason, - userFacing: details?.userFacing ?? this.userFacing, - }, - details?.stack ?? callerStack() - ); - } - - index(this: DebugDescription, index: number): interfaces.Description { - return new DebugDescription( - this.#extendId(index), - "formula", - this.#api, - { - type: "member", - parent: this, - kind: "index", - name: index, - }, - undefined, - this.#stack - ); - } - - /** - * A key represents a string that the user wrote in their source code. In contrast, `detail`, - * represents a user-facing *concept* that created by Starbeam, and `implementation` represents - * a concept that normal users don't have enough context to understand (but which can be - * revealed by passing `implementation: true` to the debug APIs). - */ - key( - this: DebugDescription, - name: string, - options?: { id?: string | number; note?: string } - ): interfaces.Description { - return new DebugDescription( - this.#extendId(options?.id ? [name, options.id] : name), - "formula", - this.#api, - { - type: "member", - kind: "key", - parent: this, - name, - note: options?.note, - }, - undefined, - this.#stack - ); - } - - method( - this: DebugDescription, - id: interfaces.ReactiveId | symbol, - name: string, - args?: interfaces.DescriptionArgument[] | undefined - ): interfaces.Description { - if (typeof id === "symbol") { - verify( - id, - isEqual(REUSE_ID), - expected - .as("symbol passed to desc.method()") - .toBe("REUSE_ID") - .butGot((s) => String(s)) - ); - } - - return new DebugDescription( - this.#newId(id), - "formula", - this.#api, - { - type: "method", - parent: this, - name, - args, - }, - undefined, - this.#stack - ); - } - - #name(options: interfaces.DescriptionDescribeOptions): string { - const color = options.color ?? true; - const getName = (): string => { - if ((this.isAnonymous || options.source) ?? false) { - return `${this.#fullName(color)} @ ${this.#caller(options)}`; - } else { - return this.fullName; - } - }; - - const name = getName(); - - if (!this.isAnonymous && options.id) { - return `${name} (${this.#idName})`; - } else { - return name; - } - } - - #newId(id: interfaces.ReactiveId | REUSE_ID): interfaces.ReactiveId { - return id === REUSE_ID ? this.#id : id; - } - - property(this: DebugDescription, name: string): interfaces.Description { - return new DebugDescription( - this.#extendId(name), - "formula", - this.#api, - { - type: "member", - parent: this, - kind: "property", - name, - }, - undefined, - this.#stack - ); - } - - withId(id?: interfaces.ReactiveId): interfaces.Description { - if (id === undefined) { - return this as interfaces.Description; - } - - return new DebugDescription( - id, - this.#type, - this.#api, - this.#details, - this.#internal, - this.#stack - ) as interfaces.Description; - } - - withStack( - stack: Stack, - id: interfaces.ReactiveId | symbol - ): interfaces.Description { - if (typeof id === "symbol") { - verify( - id, - isEqual(REUSE_ID), - expected - .as("symbol passed to withStack") - .toBe("REUSE_ID") - .butGot((s) => String(s)) - ); - } - - return new DebugDescription( - this.#newId(id as REUSE_ID), - this.#type, - this.#api, - this.#details, - this.#internal, - stack - ) as interfaces.Description; - } - } - - PickedDescription = DebugDescription; -} else { - class ProdDescription implements interfaces.Description { - readonly api = ""; - - readonly frame: interfaces.StackFrame = { - starbeamCaller: undefined, - parts: () => new DisplayParts({ path: "" }), - link: () => "", - display: () => "", - }; - - readonly fromUser = undefined; - readonly fullName = ""; - readonly name = ""; - readonly id: interfaces.ReactiveId = "@starbeam:erased"; - readonly internal = undefined; - readonly parts: interfaces.DescriptionParts = { - api: { name: "erased" }, - id: "erased", - details: { type: "anonymous" }, - userFacing: this, - type: "erased", - frame: undefined, - stack: undefined, - }; - - readonly stack = undefined; - readonly type = "erased"; - - readonly userFacing = this; - - static PROD = new ProdDescription(); - - static from(): interfaces.Description { - return ProdDescription.PROD; - } - - static is(description: unknown): description is interfaces.Description { - return !!(description && description instanceof ProdDescription); - } - - forApi(): interfaces.Description { - return this; - } - - asImplementation(): interfaces.Description { - return this; - } - - describe(): string { - return ""; - } - - detail(): interfaces.Description { - return this; - } - - implementation(): interfaces.Description { - return this; - } - - index(): interfaces.Description { - return this; - } - - key(): interfaces.Description { - return this; - } - - method(): interfaces.Description { - return this; - } - - property(): interfaces.Description { - return this; - } - - withId(): interfaces.Description { - return this; - } - - withStack(): interfaces.Description { - return this; - } - } - - PickedDescription = ProdDescription; -} - -export type Description = interfaces.Description; -export const Description: DescriptionStatics = PickedDescription; diff --git a/packages/universal/debug/src/description/interface.ts b/packages/universal/debug/src/description/interface.ts new file mode 100644 index 00000000..153484d8 --- /dev/null +++ b/packages/universal/debug/src/description/interface.ts @@ -0,0 +1,7 @@ +import type { Description, ReactiveType } from "@starbeam/interfaces"; + +export type DescriptionRuntime = ( + type: ReactiveType, + specified: string | undefined, + create?: (desc: Description) => Description +) => Description | undefined; diff --git a/packages/universal/debug/src/description/prod.ts b/packages/universal/debug/src/description/prod.ts new file mode 100644 index 00000000..34b97da3 --- /dev/null +++ b/packages/universal/debug/src/description/prod.ts @@ -0,0 +1,3 @@ +import type { DescriptionRuntime } from "./interface.js"; + +export default (() => undefined) satisfies DescriptionRuntime; diff --git a/packages/universal/debug/src/entry-point.ts b/packages/universal/debug/src/entry-point.ts deleted file mode 100644 index 4d55b24e..00000000 --- a/packages/universal/debug/src/entry-point.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { Stack } from "./stack.js"; -import { callerStack } from "./stack.js"; - -let STACK: Stack | null = null; -const CALLER_FRAME = 1; - -export function entryPoint(callback: () => T): T { - // the outermost entry point wins. - if (import.meta.env.DEV && !STACK) { - try { - STACK = callerStack(CALLER_FRAME); - return callback(); - } finally { - STACK = null; - } - } else { - return callback(); - } -} diff --git a/packages/universal/debug/src/logged.ts b/packages/universal/debug/src/logged.ts deleted file mode 100644 index 56c18451..00000000 --- a/packages/universal/debug/src/logged.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { LOGGER } from "./logger.js"; - -const loggedFunction = { - logged: undefined as LoggedFunction | undefined, -}; - -type LoggedFunction = (value: T, log?: (value: T) => void) => T; - -if (import.meta.env.DEV) { - loggedFunction.logged = ( - value: T, - log: (value: T) => void = LOGGER.info.log - ) => { - log(value); - return value; - }; -} else { - loggedFunction.logged = (value: T) => value; -} - -export const logged = loggedFunction.logged; diff --git a/packages/universal/debug/src/logger.ts b/packages/universal/debug/src/logger.ts deleted file mode 100644 index 8a4121bf..00000000 --- a/packages/universal/debug/src/logger.ts +++ /dev/null @@ -1,137 +0,0 @@ -export enum LogLevel { - Trace = 0, - Debug = 1, - Info = 2, - Warn = 3, - Error = 4, - Fatal = 5, -} - -export class LoggerAsLevel { - #logger: Logger; - #level: LogLevel; - #config: LoggerConfig; - - constructor(logger: Logger, level: LogLevel, config: LoggerConfig) { - this.#logger = logger; - this.#level = level; - this.#config = config; - } - - log = (arg: unknown, ...args: unknown[]): void => { - if (this.#level >= this.#config.minimum) { - this.#logger.send(this.#level, { args: [arg, ...args] }); - } - }; - - get withStack(): LoggerWithStack { - return new LoggerWithStack(this.#logger, this.#level, this.#config); - } -} - -export class LoggerWithStack { - #logger: Logger; - #level: LogLevel; - #config: LoggerConfig; - - constructor(logger: Logger, level: LogLevel, config: LoggerConfig) { - this.#logger = logger; - this.#level = level; - this.#config = config; - } - - log(arg: unknown, ...args: unknown[]): void { - if (this.#level >= this.#config.minimum) { - this.#logger.send(this.#level, { args: [arg, ...args], stack: true }); - } - } -} - -interface LoggerConfig { - readonly minimum: LogLevel; -} - -export class Logger { - #console: Console; - #config: LoggerConfig; - - readonly trace: LoggerAsLevel; - readonly debug: LoggerAsLevel; - readonly info: LoggerAsLevel; - readonly warn: LoggerAsLevel; - readonly error: LoggerAsLevel; - readonly fatal: LoggerAsLevel; - - constructor(console: Console, config: LoggerConfig) { - this.#console = console; - this.#config = config; - - this.trace = new LoggerAsLevel(this, LogLevel.Trace, config); - this.debug = new LoggerAsLevel(this, LogLevel.Debug, config); - this.info = new LoggerAsLevel(this, LogLevel.Info, config); - this.warn = new LoggerAsLevel(this, LogLevel.Warn, config); - this.error = new LoggerAsLevel(this, LogLevel.Error, config); - this.fatal = new LoggerAsLevel(this, LogLevel.Fatal, config); - } - - set level(level: LogLevel) { - this.#config = { ...this.#config, minimum: level }; - } - - get isVerbose(): boolean { - return this.#config.minimum === LogLevel.Trace; - } - - get isDebug(): boolean { - return this.#config.minimum <= LogLevel.Debug; - } - - configure(config: Partial): void { - Object.assign(this.#config, config); - } - - send( - level: LogLevel, - { args, stack }: { args: unknown[]; stack?: boolean } - ): void { - if (level === LogLevel.Trace) { - if (stack) { - this.#console.trace(...args); - } else { - this.#console.debug(...args); - } - } - - this.#console.groupCollapsed("stack trace"); - this.#console.trace(); - this.#console.groupEnd(); - - switch (level) { - case LogLevel.Trace: - if (stack) { - this.#console.trace(...args); - } else { - this.#console.debug(...args); - } - break; - case LogLevel.Debug: - this.#console.debug(...args); - break; - case LogLevel.Info: - this.#console.log(...args); - break; - case LogLevel.Warn: - this.#console.warn(...args); - break; - case LogLevel.Error: - this.#console.error(...args); - break; - case LogLevel.Fatal: - this.#console.error(...args); - break; - } - } -} -export const LOGGER = new Logger(globalThis.console, { - minimum: LogLevel.Warn, -}); diff --git a/packages/universal/debug/src/message.ts b/packages/universal/debug/src/message.ts deleted file mode 100644 index bd015735..00000000 --- a/packages/universal/debug/src/message.ts +++ /dev/null @@ -1,171 +0,0 @@ -export class Style { - static create(property: string, value: string): Style { - return new Style(property, value); - } - - #property: string; - #value: string; - - constructor(property: string, value: string) { - this.#property = property; - this.#value = value; - } - - toCSS(): string { - return `${this.#property}: ${this.#value};`; - } -} - -export class Styles { - #styles: Style[] = []; - - add(property: string, value: string): void { - this.#styles.push(Style.create(property, value)); - } - - toCSS(): string { - return this.#styles.map((style) => style.toCSS()).join(" "); - } -} - -export class Fragment { - #content: string; - #styles: Styles = new Styles(); - - constructor(content: string) { - this.#content = content; - } - - css(style: `${string}:${string}`): this { - const [property, value] = style.split(":") as [string, string]; - this.#styles.add(property.trim(), value.trim()); - return this; - } - - append(buffer: Buffer): void { - buffer.add(this.#content, this.#styles.toCSS()); - } -} - -export function Styled(content: string): Fragment { - return new Fragment(content); -} - -export type IntoFragment = - | string - | [content: string, ...styles: `${string}:${string}`[]]; - -export type IntoBlock = IntoFragment[] | ""; - -export class Block { - #fragments: Fragment[] = []; - - add(fragment: Fragment | string): void { - if (typeof fragment === "string") { - this.#fragments.push(new Fragment(fragment)); - } else { - this.#fragments.push(fragment); - } - } - - appendTo(buffer: Buffer): void { - for (const fragment of this.#fragments) { - fragment.append(buffer); - } - } -} - -export class Blocks { - #blocks: Block[] = []; - - add(block: Block | string): void { - if (typeof block === "string") { - const b = new Block(); - b.add(block); - this.#blocks.push(new Block()); - } else { - this.#blocks.push(block); - } - } - - appendTo(buffer: Buffer): void { - for (const block of this.#blocks) { - block.appendTo(buffer); - buffer.break(); - } - } -} - -export function Message( - into: IntoBlock[], - options?: { plain: boolean } -): unknown[] { - const blocks = new Blocks(); - - for (const intoBlock of into) { - const block = new Block(); - for (const fragment of intoBlock) { - if (typeof fragment === "string") { - block.add(fragment); - } else { - const [content, ...styles] = fragment; - - const f = Styled(content); - - for (const style of styles) { - f.css(style); - } - - block.add(f); - } - } - blocks.add(block); - } - - const buffer = new Buffer(options?.plain ?? false); - - blocks.appendTo(buffer); - - return buffer.message(); -} - -class Buffer { - static styled(): Buffer { - return new Buffer(false); - } - - static plain(): Buffer { - return new Buffer(true); - } - - #message: string[] = []; - #current = ""; - #styles: string[] = []; - #plain: boolean; - - constructor(plain: boolean) { - this.#plain = plain; - } - - add(content: string, style?: string): void { - if (style && !this.#plain) { - this.#current += `%c${content}`; - this.#styles.push(style); - } else { - this.#current += content; - } - } - - message(): unknown[] { - if (this.#current) { - this.break(); - } - - return [this.#message.join("\n"), ...this.#styles]; - } - - break(): void { - this.#message.push(this.#current); - this.#current = ""; - } -} diff --git a/packages/universal/debug/src/module.ts b/packages/universal/debug/src/module.ts deleted file mode 100644 index 6937589f..00000000 --- a/packages/universal/debug/src/module.ts +++ /dev/null @@ -1,287 +0,0 @@ -import { isPresentString } from "@starbeam/core-utils"; -import type * as interfaces from "@starbeam/interfaces"; -import { hasType } from "@starbeam/verify"; - -import { inspector } from "./inspect/inspect-support.js"; - -export function describeModule(module: string): DescribedModule { - return new DescribedModule(parse(module)); -} - -export interface DisplayRoot { - name?: string; - prefix: string; -} - -export class DisplayPathParts { - readonly #path: string; - readonly #root: DisplayRoot | undefined; - - constructor({ path, root }: { path: string; root?: DisplayRoot }) { - this.#path = path; - this.#root = root; - } - - finish(options: { action?: string; loc?: Loc } = {}): DisplayParts { - return new DisplayParts({ path: this.#path, root: this.#root, ...options }); - } -} - -export class DisplayParts implements interfaces.DisplayParts { - readonly #action: string | undefined; - readonly #loc: Loc | undefined; - readonly #path: string; - readonly #root: DisplayRoot | undefined; - - static { - inspector(this, "DisplayParts").define((parts, debug) => - debug.struct({ - path: parts.#path, - root: parts.#root, - action: parts.#action, - loc: parts.#loc, - }) - ); - } - - constructor({ - path, - root, - action, - loc, - }: { - path: string; - root?: DisplayRoot | undefined; - action?: string | undefined; - loc?: Loc | undefined; - }) { - this.#path = path; - this.#root = root; - this.#action = action; - this.#loc = loc; - } - - get action(): string | undefined { - return this.#action; - } - - get #displayPath(): string { - if (this.#root?.name) { - return `[${this.#root.name}]/${this.#path}`; - } else { - return this.#path; - } - } - - get loc(): Loc | undefined { - return this.#loc; - } - - get path(): string { - return this.#path; - } - - get root(): DisplayRoot | undefined { - return this.#root; - } - - display(): string { - if (this.#loc && this.#action) { - return `${this.#action} (${this.#displayPath}:${formatLoc(this.#loc)})`; - } else if (this.#loc) { - return `${this.#displayPath}:${formatLoc(this.#loc)}`; - } else if (this.#action) { - return `${this.#action} (${this.#displayPath})`; - } else { - return this.#displayPath; - } - } -} - -export class DescribedModule { - #module: DescribedModulePath | DescribedPackage; - - constructor(module: DescribedModulePath | DescribedPackage) { - this.#module = module; - } - - display( - location?: { loc?: Loc | undefined; action?: string | undefined }, - options: interfaces.StackFrameDisplayOptions = {} - ): string { - return this.parts(location, options).display(); - } - - parts( - location?: { loc?: Loc | undefined; action?: string | undefined }, - options: interfaces.StackFrameDisplayOptions = {} - ): DisplayParts { - const parts = this.#module.parts(options); - - if (location === undefined) { - return parts.finish(); - } - - const { loc, action } = location; - - const hasLoc = loc !== undefined; - const hasAction = isPresentString(action); - - if (hasLoc && hasAction) { - return parts.finish({ action, loc }); - } else if (hasLoc) { - return parts.finish({ loc }); - } else if (hasAction) { - return parts.finish({ action }); - } - - return parts.finish(); - } -} - -interface Loc { - line: number; - column?: number | undefined; -} - -function formatLoc(loc: Loc): string { - if (loc.column === undefined) { - return `${loc.line}`; - } else { - return `${loc.line}:${loc.column}`; - } -} - -interface DescribedPath { - // path(options?: StackFrameDisplayOptions): string; - parts: (options?: interfaces.StackFrameDisplayOptions) => DisplayPathParts; -} - -class DescribedModulePath implements DescribedPath { - readonly #path: string; - readonly pkg = null; - readonly type = "relative"; - - constructor(path: string) { - this.#path = path; - } - - [Symbol.for("nodejs.util.inspect.custom")](): string { - return `DescribedModulePath(${this.#path})`; - } - - parts(options?: interfaces.StackFrameDisplayOptions): DisplayPathParts { - return relative({ ...options, full: normalize(this.#path) }); - } -} - -class DescribedPackage implements DescribedPath { - readonly #name: string; - readonly #path: string; - readonly #scope: string | undefined; - readonly type = "package"; - - constructor(scope: string, name: string, path: string) { - this.#scope = scope; - this.#name = name; - this.#path = path; - } - - get #fullPath(): string { - const parts: string[] = []; - - if (this.#scope) { - parts.push(this.#scope); - } - - parts.push(this.#name); - - if (this.#path) { - parts.push(this.#path); - } - - return normalize(...parts); - } - - get pkg(): string { - return normalize(this.#scope, this.#name); - } - - [Symbol.for("nodejs.util.inspect.custom")](): string { - const path = this.#path ? ` at ${this.#path}` : ""; - - if (this.#scope) { - return `DescribedPackage(${this.#scope}/${this.#name}${path})`; - } else { - return `DescribedPackage(${this.#name}${path})`; - } - } - - parts(): DisplayPathParts { - return new DisplayPathParts({ path: this.#fullPath }); - } -} - -const SOURCE_PARTS = - /^(?![a-z]+:)(?:(?@[^/\\]+)[/])?(?[^/\\]+)(?:[/\\](?.*))?$/; - -function parse(module: string): DescribedModulePath | DescribedPackage { - if (module.startsWith(".") || module.startsWith("/")) { - return new DescribedModulePath(module); - } - - const groups = SOURCE_PARTS.exec(module)?.groups; - - if (groups === undefined) { - return new DescribedModulePath(module); - } - - const { scope, name, path } = groups as { - scope: string; - name: string; - path: string; - }; - - return new DescribedPackage(scope, name, path); -} - -/** - * The whole `Stack` system is only intended to be used for logging, so the - * edge-cases where this normalization wouldn't work (verbatim paths on Windows) - * shouldn't matter. - */ -function normalize(...pathParts: (string | null | undefined)[]): string { - return pathParts - .filter(hasType("string")) - .map((p: string) => p.replaceAll(/[\\]/g, "/")) - .join("/"); -} - -function relative({ - root, - roots, - full, -}: { - root?: string; - roots?: Record; - full: string; -}): DisplayPathParts { - if (root && full.startsWith(root)) { - const path = full.slice(root.length); - const rel = path.startsWith("/") ? path.slice("/".length) : path; - return new DisplayPathParts({ root: { prefix: root }, path: rel }); - } else if (roots) { - for (const [key, value] of Object.entries(roots)) { - if (full.startsWith(value)) { - const path = full.slice(value.length); - const r = path.startsWith("/") ? path.slice("/".length) : path; - return new DisplayPathParts({ - root: { name: key, prefix: value }, - path: r, - }); - } - } - } - - return new DisplayPathParts({ path: full }); -} diff --git a/packages/universal/debug/src/stack.ts b/packages/universal/debug/src/stack.ts deleted file mode 100644 index 7767dc3a..00000000 --- a/packages/universal/debug/src/stack.ts +++ /dev/null @@ -1,599 +0,0 @@ -/// - -import { getFirst, type UnknownFn } from "@starbeam/core-utils"; -import type { - DescriptionArgs, - DescriptionDetails, - ReactiveId, - Stack as StackProtocol, - StackFrame, - StackFrameDisplayOptions, -} from "@starbeam/interfaces"; -import type * as interfaces from "@starbeam/interfaces"; -import { getID } from "@starbeam/shared"; -import { hasType, isObject, verified } from "@starbeam/verify"; -import { default as StackTracey } from "stacktracey"; - -import { Description } from "./description/impl.js"; -import { inspector } from "./inspect/inspect-support.js"; -import { describeModule } from "./module.js"; - -interface ErrorWithStack extends Error { - stack: string; -} - -export interface StackStatics { - readonly EMPTY: StackProtocol; - - create: (this: void, internal?: number) => StackProtocol; - fromStack: (stack: string) => StackProtocol; - - from: ((error: ErrorWithStack) => StackProtocol) & - ((error: unknown) => StackProtocol | null); - - id: ( - this: void, - description?: string | Description | { id: ReactiveId } - ) => ReactiveId; - - description: ( - this: void, - args: DescriptionArgs & { - fromUser?: - | string - | DescriptionDetails - | interfaces.Description - | undefined; - }, - internal?: number - ) => interfaces.Description; - - desc: ( - type: interfaces.DescriptionType, - fromUser?: string | DescriptionDetails | interfaces.Description | undefined, - internal?: number | undefined - ) => interfaces.Description; - - fromCaller: (this: void, internal?: number) => StackProtocol; - - replaceFrames: (error: unknown, fromStack: StackProtocol) => void; - - /** - * Erase an abstraction from the call stack so the test error points at the user code, rather than - * the abstraction's code. - * - * Call a callback, and if the callback throws an exception, remove the current frame and all of the - * frames invoked by the current frame from the call stack. - * - * If you want to erase additional **caller** frames (because the code that calls the callback is - * not the direct call site from user code), you can specify an additional number of frames to erase - * using the `internal` parameter. - */ - entryPoint: ( - this: void, - callback: () => T, - options?: { internal?: number; stack?: StackProtocol } - ) => T; -} - -let PickedStack: StackStatics; - -const MISSING = -1; -const START = 0; - -if (import.meta.env.DEV) { - Error.stackTraceLimit = 1000; - - class ParsedStack { - static empty(): ParsedStack { - return new ParsedStack("", "", "", []); - } - - static parse({ stack }: { stack: string }): ParsedStack { - const parsed = new StackTracey(stack); - const frames = parsed.items; - - const [firstFrame] = frames; - - if (firstFrame === undefined) { - return new ParsedStack(stack, stack, "", []); - } - - const first = firstFrame.beforeParse; - const lines = stack.split("\n"); - - const offset = lines.findIndex((line) => line.trim() === first); - - if (offset === MISSING) { - throw Error( - `An assumption was incorrect: A line that came from StackTracey cannot be found in the original trace.\n\n== Stack ==\n\n${stack}\n\n== Line ==\n\n${first}` - ); - } - - // the header is all of the lines before the offset - const header = lines.slice(START, offset).join("\n"); - const rest = lines.slice(offset).join("\n"); - - return new ParsedStack( - stack, - header, - rest, - frames.map((f) => StackFrame.from(parsed, f)) - ); - } - - static { - inspector(this, "ParsedStack").define((stack, debug) => - debug.struct({ - header: stack.#header, - frames: stack.#frames.map((f) => f.parts().display()), - rest: stack.#rest, - }) - ); - } - - readonly #source: string; - readonly #header: string; - readonly #rest: string; - readonly #frames: readonly StackFrame[]; - - private constructor( - source: string, - header: string, - rest: string, - frames: readonly StackFrame[] - ) { - this.#source = source; - this.#header = header; - this.#rest = rest; - this.#frames = frames; - } - - get header(): string { - return this.#header; - } - - get entries(): readonly StackFrame[] { - return this.#frames; - } - - /** - * The formatted stack trace, suitable to be attached to `error.stack`. - */ - get stack(): string { - return `${this.#header}\n${this.#rest}`; - } - - replaceFrames(stack: ParsedStack): ParsedStack { - return new ParsedStack( - this.#source, - this.#header, - stack.#rest, - stack.#frames - ); - } - - slice(n: number): ParsedStack { - const rest = this.#rest.split("\n").slice(n).join("\n"); - return new ParsedStack( - this.#source, - this.#header, - rest, - this.#frames.slice(n) - ); - } - } - - const REPLACED_ERRORS = new WeakSet(); - const INITIAL_INTERNAL_FRAMES = 0; - const INITIAL_ENTRY_POINT_FRAMES = 1; - const CALLER = 1; - const ABSTRACTION_CALLER = 2; - - class DebugStack implements StackProtocol { - static EMPTY = new DebugStack(ParsedStack.empty()); - - static create(this: void, internal = INITIAL_INTERNAL_FRAMES): DebugStack { - const ErrorClass = Error; - - if ("captureStackTrace" in ErrorClass) { - const err = {} as { stack: string }; - ErrorClass.captureStackTrace(err, DebugStack.create); - - return DebugStack.fromStack(err.stack).slice(internal); - } else { - const stack = Error( - "An error created in the internals of Stack.create" - ).stack; - return DebugStack.fromStack(verified(stack, hasType("string"))).slice( - internal + CALLER - ); - } - } - - static fromCaller( - this: void, - internal = INITIAL_INTERNAL_FRAMES - ): DebugStack { - // Remove *this* `fromCaller` frame from the stack *and* the caller's frame - return DebugStack.create(internal + ABSTRACTION_CALLER); - } - - static fromStack(stack: string): DebugStack { - return new DebugStack(ParsedStack.parse({ stack })); - } - - /** - * Replace the stack frames in the specified error with the stack frames from the specified stack, - * but leave the header from the specified error. - * - * If the error is not an Error with a stack, this function does nothing. - */ - static replaceFrames(error: unknown, fromStack: Stack): void { - if (isErrorWithStack(error)) { - const errorStack = DebugStack.from(error); - errorStack.withReplacedFrames(fromStack as DebugStack); - error.stack = errorStack.stack; - } - } - - static from(error: ErrorWithStack): DebugStack; - static from(error: unknown): DebugStack | null; - static from(error: unknown): DebugStack | null { - if (isErrorWithStack(error)) { - return new DebugStack(ParsedStack.parse(error)); - } else { - return null; - } - } - - static description( - args: DescriptionArgs & { - fromUser?: - | string - | DescriptionDetails - | interfaces.Description - | undefined; - }, - internal = INITIAL_INTERNAL_FRAMES - ): interfaces.Description { - const stack = DebugStack.fromCaller(internal + CALLER); - const fromUser = args.fromUser; - - const api: string | interfaces.ApiDetails | undefined = args.api ?? {}; - - if (typeof api !== "string" && api.package === undefined) { - const starbeam = stack.caller?.starbeamCaller; - - if (starbeam) { - api.package = starbeam.package; - api.name = starbeam.name; - } - } - - if (fromUser === undefined || typeof fromUser === "string") { - return Description.from({ ...args, stack }); - } else if (Description.is(fromUser)) { - return fromUser.withId(args.id); - } else { - return Description.from({ ...args, stack }); - } - } - - static desc( - type: interfaces.DescriptionType, - fromUser?: - | string - | DescriptionDetails - | interfaces.Description - | undefined, - internal = INITIAL_INTERNAL_FRAMES - ): interfaces.Description { - return DebugStack.description( - { - type, - fromUser, - }, - internal + CALLER - ); - } - - static id( - this: void, - description?: string | { id: ReactiveId } - ): ReactiveId { - if (description === undefined || typeof description === "string") { - return getID(); - } else { - return description.id; - } - } - - static callerFrame( - internal = INITIAL_INTERNAL_FRAMES - ): StackFrame | undefined { - return DebugStack.fromCaller(internal + CALLER).caller; - } - - static entryPoint( - callback: () => T, - { - internal = INITIAL_ENTRY_POINT_FRAMES, - stack = DebugStack.create(CALLER + internal), - }: { internal?: number; stack?: StackProtocol } = {} - ): T { - try { - return callback(); - } catch (e) { - if (isErrorWithStack(e) && !REPLACED_ERRORS.has(e)) { - const errorStack = DebugStack.from(e); - - const updated = errorStack.withReplacedFrames(stack as DebugStack); - e.stack = updated.stack; - REPLACED_ERRORS.add(e); - } - throw e; - } - } - - #parsed: ParsedStack; - - constructor(parsed: ParsedStack) { - this.#parsed = parsed; - } - - get entries(): readonly StackFrame[] { - return this.#parsed.entries; - } - - get caller(): StackFrame | undefined { - return getFirst(this.#parsed.entries); - } - - get header(): string { - return this.#parsed.header; - } - - /** - * The formatted stack trace, suitable to be attached to `error.stack`. - */ - get stack(): string { - return this.#parsed.stack; - } - - /** - * Replace the stack frames with the current Stack with the frames from the given Stack, but keep - * the same header. - */ - withReplacedFrames(stack: DebugStack): DebugStack { - return new DebugStack(this.#parsed.replaceFrames(stack.#parsed)); - } - - slice(n: number): DebugStack { - if (n === START) { - return this; - } else { - return new DebugStack(this.#parsed.slice(n)); - } - } - } - - PickedStack = DebugStack; - - class StackFrame implements interfaces.StackFrame { - static from(stack: StackTracey, frame: StackTracey.Entry): StackFrame { - return new StackFrame(stack, frame, null); - } - - static { - inspector(this, "StackFrame").define((frame, debug) => - debug.struct({ original: frame.parts().display() }) - ); - } - - #stack: StackTracey; - #frame: StackTracey.Entry; - #reified: StackTracey.Entry | null; - - private constructor( - stack: StackTracey, - frame: StackTracey.Entry, - reified: StackTracey.Entry | null - ) { - this.#stack = stack; - this.#frame = frame; - this.#reified = reified; - } - - get starbeamCaller(): - | { package: string; name?: string | undefined } - | undefined { - const frame = this.#reify(); - - const pkg = /(@starbeam\/[/]+)/.exec(frame.file) as - | (RegExpExecArray & [string, string]) - | undefined; - - if (pkg) { - return { - // eslint-disable-next-line @typescript-eslint/no-magic-numbers - package: pkg[1], - name: frame.callee === "" ? undefined : frame.callee, - }; - } - } - - get action(): string { - return this.#reify().callee; - } - - get loc(): { line: number; column?: number | undefined } | undefined { - const entry = this.#reify(); - - if (entry.line === undefined) { - return undefined; - } - - return { line: entry.line, column: entry.column }; - } - - get debug(): StackTracey.Entry { - return this.#reify(); - } - - #reify(): StackTracey.Entry { - let reified = this.#reified; - - if (!reified) { - this.#reified = reified = this.#stack.withSource(this.#frame); - } - - return reified; - } - - link(options?: StackFrameDisplayOptions): string { - if (options?.complete) { - return this.#stack.items.map((entry) => entry.beforeParse).join("\n"); - } - - const module = describeModule(this.#reify().file); - return module.display({ loc: this.loc }, options); - } - - fullStack(): string { - return this.#stack.asTable(); - } - - display(options?: StackFrameDisplayOptions): string { - const module = describeModule(this.#reify().file); - return module.display({ action: this.action, loc: this.loc }, options); - } - - parts( - options?: StackFrameDisplayOptions | undefined - ): interfaces.DisplayParts { - const module = describeModule(this.#reify().file); - return module.parts({ action: this.action, loc: this.loc }, options); - } - } -} else { - /** - * A stub implementation of the `Stack` infrastructure that doesn't do anything. - */ - class ProdStack implements StackProtocol { - static EMPTY = new ProdStack(); - - static create(this: void): StackProtocol { - return ProdStack.EMPTY; - } - - static fromStack(this: void): StackProtocol { - return ProdStack.EMPTY; - } - - static from(error: ErrorWithStack): StackProtocol; - static from(error: unknown): StackProtocol | null; - static from(): StackProtocol | null { - return ProdStack.EMPTY; - } - - static replaceFrames(): void { - return; - } - - static description( - args: DescriptionArgs & { - fromUser?: - | string - | DescriptionDetails - | interfaces.Description - | undefined; - } - ): interfaces.Description { - return Description.from({ ...args, stack: ProdStack.EMPTY }); - } - - static desc( - type: interfaces.DescriptionType, - fromUser?: - | string - | DescriptionDetails - | interfaces.Description - | undefined - ): interfaces.Description { - return ProdStack.description({ - type, - stack: ProdStack.EMPTY, - fromUser, - }); - } - - static id(): ReactiveId { - return getID(); - } - - static callerFrame(): StackFrame | undefined { - return undefined; - } - - static fromCaller(): StackProtocol { - return ProdStack.EMPTY; - } - - static entryPoint(callback: () => T): T { - return callback(); - } - - readonly caller: StackFrame | undefined = undefined; - readonly stack: string = ""; - } - - PickedStack = ProdStack; -} - -export const Stack: StackStatics = PickedStack; -export type Stack = interfaces.Stack; -export const entryPoint = PickedStack.entryPoint; - -export function entryPointFn( - fn: F, - options?: { stack: Stack } -): F { - return ((...args: unknown[]) => - entryPoint(() => fn(...args), { internal: 1, ...options })) as F; -} - -export function entryPoints( - funcs: Funcs, - options?: { stack: Stack } -): Funcs { - const result = Object.create(null) as Record; - - for (const [key, fn] of Object.entries(funcs) as [string, UnknownFn][]) { - if (typeof fn === "function") { - result[key] = entryPointFn(fn, options); - } else { - result[key] = fn; - } - } - - return result as Funcs; -} - -/** This should be convertable to something like Description.EMPTY in prod builds */ -export const descriptionFrom = PickedStack.description; -export const Desc = PickedStack.desc; - -/** - * If it isn't already removed, this should be convertable to getID in prod builds - */ -export const idFrom = PickedStack.id; - -export const callerStack: (this: void, internal?: number) => StackProtocol = - PickedStack.fromCaller; - -export function isErrorWithStack(error: unknown): error is ErrorWithStack { - return ( - isObject(error) && error instanceof Error && typeof error.stack === "string" - ); -} diff --git a/packages/universal/debug/src/tag.ts b/packages/universal/debug/src/tag.ts index a8866691..fd682baa 100644 --- a/packages/universal/debug/src/tag.ts +++ b/packages/universal/debug/src/tag.ts @@ -1,29 +1,28 @@ import { isPresent } from "@starbeam/core-utils"; -import type { Tag } from "@starbeam/interfaces"; +import type { Description, Tag } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { Tree } from "./tree.js"; +RUNTIME; + export const debugTag = ( tag: Tag, { implementation = false, - source = false, - id = false, }: { implementation?: boolean; source?: boolean; id?: boolean } = {} ): string => { const dependencies = [...tag.dependencies()]; const descriptions = new Set( - dependencies.map((dependency) => { - return implementation - ? dependency.description - : dependency.description.userFacing; - }) + dependencies.map((dependency) => + getDesc(dependency.description, implementation) + ) ); const nodes = [...descriptions] .map((d) => { - const description = implementation ? d : d.userFacing; - return description.describe({ source, id }); + const description = getDesc(d, implementation); + return describe(description); }) .filter(isPresent); @@ -37,9 +36,34 @@ export const logTag = ( const debug = debugTag(tag, options); console.group( - tag.description.describe({ id: options.id }), + describe(tag.description, { id: options.id }), `(updated at ${tag.lastUpdated.toString({ format: "timestamp" })})` ); console.log(debug); console.groupEnd(); }; + +function describe( + description: Description | undefined, + options?: { id: boolean | undefined } +): string { + if (description) { + return ( + RUNTIME.debug?.describe(description, options) ?? + "an unknown reactive value" + ); + } else { + return "an unknown reactive value"; + } +} + +function getDesc( + description: Description | undefined, + showImplementation: boolean +): Description | undefined { + if (showImplementation) { + return description; + } else { + return RUNTIME.debug?.getUserFacing(description); + } +} diff --git a/packages/universal/debug/src/timeline.ts b/packages/universal/debug/src/timeline.ts deleted file mode 100644 index e12a3147..00000000 --- a/packages/universal/debug/src/timeline.ts +++ /dev/null @@ -1,351 +0,0 @@ -import type { - CellTag, - Diff, - FormulaTag, - Stack, - Tag, - Tagged, - Timestamp, -} from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; -import { exhaustive } from "@starbeam/verify"; - -interface Runtime { - getTag: (reactive: Tagged) => Tag; -} - -function reactiveInternals(reactive: Tagged): Tag { - return reactive[TAG]; -} - -interface OperationInfo { - readonly at: Timestamp; - readonly for: I; - readonly caller: Stack; -} - -export type DebugOperationOptions = - | CellConsumeOperation - | CellUpdateOperation - | FrameConsumeOperation; - -export class LeafOperation { - #data: OperationInfo; - - constructor(data: OperationInfo) { - this.#data = data; - } - - get at(): Timestamp { - return this.#data.at; - } - - get caller(): Stack { - return this.#data.caller; - } - - get for(): I { - return this.#data.for; - } -} - -export class CellConsumeOperation extends LeafOperation { - readonly type = "cell:consume"; -} - -export class CellUpdateOperation extends LeafOperation { - readonly type = "cell:update"; -} - -interface FrameConsumeInfo extends OperationInfo { - readonly diff: Diff; - readonly formula: FormulaTag; -} - -export class FrameConsumeOperation extends LeafOperation { - readonly #diff: Diff; - readonly #formula: FormulaTag; - readonly type = "frame:consume"; - - constructor(data: FrameConsumeInfo) { - super(data); - this.#diff = data.diff; - this.#formula = data.formula; - } - - get diff(): Diff { - return this.#diff; - } - - get formula(): FormulaTag { - return this.#formula; - } -} -export class MutationLog { - readonly type = "mutation"; - // This makes `DebugOperation.for` ==== `ReactiveInternals | undefined`, which makes it possible - // to easily compare the `for` value without a lot of extra type shenanigans. - readonly for: Tag | undefined = undefined; - - readonly #at: Timestamp; - #description: string; - #children = new Set(); - #parent: MutationLog | null; - - constructor(at: Timestamp, description: string, parent: MutationLog | null) { - this.#at = at; - this.#description = description; - this.#parent = parent; - } - - get at(): Timestamp { - return this.#at; - } - - add(child: DebugOperation): void { - this.#children.add(child); - } -} - -export type DebugOperation = - | CellConsumeOperation - | CellUpdateOperation - | FrameConsumeOperation - | MutationLog; - -export interface Flush { - readonly history: DebugOperation[]; - for: (reactive: Tagged) => readonly DebugOperation[]; -} - -export type DebugListener = InstanceType; - -export type DebugFilter = - | { type: "by-reactive"; reactive: Tagged } - | { type: "all" } - | { type: "none" }; - -function filterToPredicate( - filter: DebugFilter, - reactive: Runtime -): ((operation: DebugOperation) => boolean) | undefined { - switch (filter.type) { - case "by-reactive": { - const dependencies = reactive.getTag(filter.reactive).dependencies(); - // const dependencies = reactiveDependencies(filter.reactive).children() - // .dependencies; - - return (operation) => { - if (operation.for === undefined) { - return false; - } else if (operation.for.type === "cell") { - // if the operation is for a dependency of the reactive we're - // filtering by, then it's a match. - return [...dependencies].includes(operation.for); - } else { - return false; - } - }; - } - case "all": - return; - case "none": - return () => false; - default: - exhaustive(filter); - } -} - -const INITIAL_OFFSET = 0; - -export class DebugTimeline { - #timestamp: { now: () => Timestamp }; - #statics: Runtime; - #trimOffset = INITIAL_OFFSET; - #operationList: DebugOperation[] = []; - #currentMutation: MutationLog | null = null; - #listeners = new Set(); - - static Flush = class Flush { - constructor(readonly history: DebugOperation[]) {} - - for(reactive: Tagged): DebugOperation[] { - const internals = reactiveInternals(reactive); - return this.history.filter((item) => item.for === internals); - } - }; - - static DebugListener = class DebugListener { - #timeline: DebugTimeline; - #offset = INITIAL_OFFSET; - #filter: DebugFilter; - #notify: () => void; - - constructor( - timeline: DebugTimeline, - notify: () => void, - filter: DebugFilter - ) { - this.#timeline = timeline; - this.#notify = notify; - this.#filter = filter; - } - - static offset(this: void, listener: DebugListener): number { - return listener.#offset; - } - - static create( - timestamp: { now: () => Timestamp }, - statics: Runtime - ): DebugTimeline { - return new DebugTimeline(timestamp, statics); - } - - static notify(this: void, listener: DebugListener): void { - listener.#notify(); - } - - update(filter: DebugFilter): void { - this.#filter = filter; - } - - flush(): DebugOperation[] { - const flush = this.#timeline.#flush( - this.#offset, - filterToPredicate(this.#filter, this.#timeline.#statics) - ); - this.#offset = this.#timeline.#end; - this.#timeline.#prune(); - - return flush.history; - } - - detach(): void { - this.#timeline.#listeners.delete(this); - } - }; - - static create( - timestamp: { now: () => Timestamp }, - statics: Runtime - ): DebugTimeline { - return new DebugTimeline(timestamp, statics); - } - - private constructor(timestamp: { now: () => Timestamp }, statics: Runtime) { - this.#timestamp = timestamp; - this.#statics = statics; - } - - get #end(): number { - return this.#trimOffset + this.#operationList.length; - } - - notify(): void { - this.#listeners.forEach(DebugTimeline.DebugListener.notify); - } - - attach( - notify: () => void, - options: { filter: DebugFilter | "all" | "none" } = { filter: "all" } - ): DebugListener { - const filter: DebugFilter = - typeof options.filter === "string" - ? { type: options.filter } - : options.filter; - - const listener = new DebugTimeline.DebugListener(this, notify, filter); - this.#listeners.add(listener); - - return listener; - } - - #flush( - offset: number, - filter?: (operation: DebugOperation) => boolean - ): Flush { - let list = this.#operationList.slice(offset - this.#trimOffset); - - if (filter) { - list = list.filter(filter); - } - - return new DebugTimeline.Flush(list); - } - - #prune(): void { - const minOffset = Math.min( - ...[...this.#listeners].map(DebugTimeline.DebugListener.offset) - ); - - const trim = minOffset - this.#trimOffset; - this.#operationList = this.#operationList.slice(trim); - this.#trimOffset = minOffset; - } - - #add(operation: DebugOperation): void { - if (this.#currentMutation) { - this.#currentMutation.add(operation); - } else { - this.#operationList.push(operation); - } - } - - #consumeCell(cell: CellTag, caller: Stack): void { - this.#add( - new CellConsumeOperation({ - at: this.#timestamp.now(), - for: cell, - caller, - }) - ); - } - - consumeCell(internals: CellTag, caller: Stack): void { - this.#consumeCell(internals, caller); - } - - consumeFrame(formula: FormulaTag, diff: Diff, caller: Stack): void { - this.#consumeFrame(formula, diff, caller); - } - - updateCell(cell: CellTag, caller: Stack): void { - this.#add( - new CellUpdateOperation({ - at: this.#timestamp.now(), - for: cell, - caller, - }) - ); - } - - #consumeFrame(formula: FormulaTag, diff: Diff, caller: Stack): void { - this.#add( - new FrameConsumeOperation({ - at: this.#timestamp.now(), - for: formula, - diff, - caller, - formula, - }) - ); - } - - mutation(description: string, callback: () => T): T { - const prev = this.#currentMutation; - const operation = new MutationLog(this.#timestamp.now(), description, prev); - - try { - this.#currentMutation = operation; - const ret = callback(); - this.#currentMutation = prev; - this.#add(operation); - - return ret; - } catch (e) { - this.#currentMutation = prev; - throw e; - } - } -} diff --git a/packages/universal/debug/tests/display.spec.ts b/packages/universal/debug/tests/display.spec.ts deleted file mode 100644 index 416fbc6e..00000000 --- a/packages/universal/debug/tests/display.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { describeModule } from "@starbeam/debug"; -import { describe, expect, test } from "vitest"; - -describe("Describing a source location", () => { - test("getting the caller when the source is a package name", () => { - const module = describeModule("@starbeam/debug"); - - expect(module.display()).toBe("@starbeam/debug"); - - expect(module.display({ loc: { line: 1, column: 1 } })).toBe( - "@starbeam/debug:1:1" - ); - - expect( - module.display({ loc: { line: 1, column: 1 }, action: "format" }) - ).toBe("format (@starbeam/debug:1:1)"); - }); - - test("getting the caller when the source is a relative path", () => { - const module = describeModule("./src/module.ts"); - - expect(module.display()).toBe("./src/module.ts"); - - expect(module.display({ loc: { line: 1, column: 1 } })).toBe( - "./src/module.ts:1:1" - ); - - expect( - module.display({ loc: { line: 1, column: 1 }, action: "format" }) - ).toBe("format (./src/module.ts:1:1)"); - }); - - test("getting the caller when the source is an absolute relative path", () => { - const module = describeModule("/workspaces/app/src/module.ts"); - - expect(module.display()).toBe("/workspaces/app/src/module.ts"); - expect(module.display({}, { root: "/workspaces/app" })).toBe( - "src/module.ts" - ); - expect(module.display({}, { roots: { app: "/workspaces/app" } })).toBe( - "[app]/src/module.ts" - ); - - expect( - module.display( - { loc: { line: 1, column: 1 } }, - { root: "/workspaces/app" } - ) - ).toBe("src/module.ts:1:1"); - - expect( - module.display( - { loc: { line: 1, column: 1 } }, - { roots: { app: "/workspaces/app" } } - ) - ).toBe("[app]/src/module.ts:1:1"); - - expect( - module.display( - { loc: { line: 1, column: 1 }, action: "format" }, - { root: "/workspaces/app" } - ) - ).toBe("format (src/module.ts:1:1)"); - - expect( - module.display( - { loc: { line: 1, column: 1 }, action: "format" }, - { roots: { app: "/workspaces/app" } } - ) - ).toBe("format ([app]/src/module.ts:1:1)"); - }); -}); diff --git a/packages/universal/debug/tests/node-inspect.spec.ts b/packages/universal/debug/tests/node-inspect.spec.ts index 46303afb..86ecd56a 100644 --- a/packages/universal/debug/tests/node-inspect.spec.ts +++ b/packages/universal/debug/tests/node-inspect.spec.ts @@ -1,4 +1,4 @@ -import { inspector } from "@starbeam/debug"; +import { inspector } from "@starbeam/core-utils"; import { describe, expect, test } from "vitest"; class Person { diff --git a/packages/universal/debug/tests/package.json b/packages/universal/debug/tests/package.json index 3c2587f8..14026ca2 100644 --- a/packages/universal/debug/tests/package.json +++ b/packages/universal/debug/tests/package.json @@ -9,6 +9,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/debug": "workspace:^" + "@starbeam/debug": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^" } } diff --git a/packages/universal/debug/tests/stack.spec.ts b/packages/universal/debug/tests/stack.spec.ts index a56b022b..7284099a 100644 --- a/packages/universal/debug/tests/stack.spec.ts +++ b/packages/universal/debug/tests/stack.spec.ts @@ -1,28 +1,26 @@ -import { callerStack } from "@starbeam/debug"; -import type { Stack } from "@starbeam/interfaces"; +import { debugRuntime } from "@starbeam/debug"; +import { type CallStack } from "@starbeam/interfaces"; import { describe, expect, test } from "vitest"; describe("Error stacks", () => { test.skipIf(() => import.meta.env.PROD)("getting the caller", () => { const anArrow = (next: () => T): T => next(); - function aFunction(): Stack { - return anOuterFunction(); + function aFunction(): string | undefined { + return anOuterFunction()?.frames[0].action; } - expect(anArrow(aFunction).caller?.display()).toMatch( - /^aFunction \([^)]*\)/ - ); - expect(anArrow(callerStackInArgs)).toMatch(/^anArrow \([^)]*\)/); + expect(anArrow(aFunction)).toEqual("aFunction"); + expect(anArrow(callerStackInArgs)).toEqual("anArrow"); }); }); -function anOuterFunction(): Stack { - return callerStack(); +function anOuterFunction(): CallStack | undefined { + return debugRuntime.callerStack(); } function callerStackInArgs( - desc = callerStack().caller?.display() + desc = debugRuntime.callerStack()?.frames[0].action ): string | undefined { return desc; } diff --git a/packages/universal/interfaces/.eslintrc.json b/packages/universal/interfaces/.eslintrc.json index e0a347c0..e239bb06 100644 --- a/packages/universal/interfaces/.eslintrc.json +++ b/packages/universal/interfaces/.eslintrc.json @@ -3,7 +3,7 @@ "overrides": [ { "extends": ["plugin:@starbeam/tight"], - "files": ["index.d.ts", "src/**/*.d.ts"], + "files": ["index.ts", "src/**/*.ts"], "parserOptions": { "project": "packages/universal/interfaces/tsconfig.json" } diff --git a/packages/universal/interfaces/index.d.ts b/packages/universal/interfaces/index.d.ts deleted file mode 100644 index 355631b7..00000000 --- a/packages/universal/interfaces/index.d.ts +++ /dev/null @@ -1,69 +0,0 @@ -export type { Unsubscribe } from "./src/aliases.js"; -export type { - ComponentNode, - EmptyRoot, - RootNode, -} from "./src/debug-protocol/tree.js"; -export type { - ApiDetails, - Description, - DescriptionArgs, - DescriptionArgument, - DescriptionDescribeOptions, - DescriptionDetails, - DescriptionParts, - DescriptionType, - DetailDescription, - DetailsPart, - MemberDescription, -} from "./src/description.js"; -export type { Diff } from "./src/diff.js"; -export type { - Frame, - FrameValidation, - InvalidFrame, - ValidFrame, -} from "./src/frame.js"; -export type { - AbstractTag, - CellTag, - DefaultMatcher, - DelegateTag, - ExhaustiveMatcher, - FormulaTag, - List, - Matcher, - Reactive, - ReactiveCell, - ReactiveFormula, - ReactiveId, - ReactiveValue, - SpecificTag, - StaticTag, - SubscriptionTarget, - Tag, - Tagged, - TaggedReactive, - TagMethods, - TagType, -} from "./src/protocol.js"; -export type { - ActiveFrame, - AutotrackingRuntime, - DebugRuntime, - DeprecatedTimeline, - Runtime, - RuntimeFrame, - SubscriptionRuntime, - UpdateOptions, -} from "./src/runtime.js"; -export type { - Stack as CallStack, - DisplayParts, - /** @deprecated use {@linkcode CallStack} */ - Stack, - StackFrame, - StackFrameDisplayOptions, -} from "./src/stack.js"; -export type { Timestamp, TimestampStatics } from "./src/timestamp.js"; -export type { Expand } from "./src/utils.js"; diff --git a/packages/universal/interfaces/index.ts b/packages/universal/interfaces/index.ts new file mode 100644 index 00000000..63066373 --- /dev/null +++ b/packages/universal/interfaces/index.ts @@ -0,0 +1,32 @@ +export type * from "./src/debug/call-stack.js"; +export type * from "./src/debug/description.js"; +export type * from "./src/debug/debug-runtime.js"; + +export type { + CellTag, + DelegateTag, + FormulaTag, + Reactive, + ReactiveCell, + ReactiveFormula, + ReactiveId, + ReactiveValue, + StaticTag, + SubscriptionTarget, + Tag, + Tagged, + TagSet, + TaggedReactive, + TagMethods, +} from "./src/protocol.js"; +export type { + ActiveFrame, + AutotrackingRuntime, + NotifyReady, + Runtime, + RuntimeFrame, + SubscriptionRuntime, + UpdateOptions, +} from "./src/runtime.js"; +export type { Timestamp, TimestampStatics } from "./src/timestamp.js"; +export type { Expand, Unsubscribe, Diff } from "./src/utils.js"; diff --git a/packages/universal/interfaces/package.json b/packages/universal/interfaces/package.json index 1141ed09..36d37ef0 100644 --- a/packages/universal/interfaces/package.json +++ b/packages/universal/interfaces/package.json @@ -2,15 +2,10 @@ "name": "@starbeam/interfaces", "version": "0.8.9", "type": "module", - "main": "index.d.ts", - "types": "index.d.ts", + "main": "index.ts", + "types": "index.ts", "exports": { - "default": "./index.d.ts" - }, - "publishConfig": { - "exports": { - "default": "./index.d.ts" - } + "default": "./index.ts" }, "starbeam": { "source": "d.ts", diff --git a/packages/universal/interfaces/src/aliases.d.ts b/packages/universal/interfaces/src/aliases.d.ts deleted file mode 100644 index 6daf8d0b..00000000 --- a/packages/universal/interfaces/src/aliases.d.ts +++ /dev/null @@ -1 +0,0 @@ -export type Unsubscribe = () => void; diff --git a/packages/universal/interfaces/src/debug-protocol/protocol.d.ts b/packages/universal/interfaces/src/debug-protocol/protocol.d.ts deleted file mode 100644 index e4c7afdc..00000000 --- a/packages/universal/interfaces/src/debug-protocol/protocol.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { ChildNode } from "./tree.js"; - -export const DEBUG = Symbol.for("starbeam.protocol:debug"); - -export interface DebugProtocol { - [DEBUG]: ChildNode; -} diff --git a/packages/universal/interfaces/src/debug-protocol/tree.d.ts b/packages/universal/interfaces/src/debug-protocol/tree.d.ts deleted file mode 100644 index da0475a5..00000000 --- a/packages/universal/interfaces/src/debug-protocol/tree.d.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type * as anydom from "@domtree/any"; - -import type { Description } from "../description.js"; -import type { Tagged } from "../protocol.js"; - -export interface INode { - readonly type: string; - readonly description: Description; -} - -export type ChildNode = ComponentNode | RouteNode; - -/** - * A `RootNode` is a node that is a valid root of a tree. Ideally, the framework has established its - * "app" concept with Starbeam, and the root node is the root of the app's tree. However, it's also - * possible to use Starbeam without an established app concept, in which case the root node is a - * component. - * - * In production mode, the root node is always `EmptyRoot`. - */ -export type RootNode = ComponentNode | AppNode | UnknownAppNode | EmptyRoot; - -export interface AppNode extends INode { - readonly type: "app"; - readonly children: ChildNode[]; -} - -export interface UnknownAppNode { - readonly type: "app:unknown"; - readonly children: ChildNode[]; -} - -export interface EmptyRoot { - readonly type: "empty"; -} - -/** - * A `RouteNode` is a node that represents an established "route" according to the frameworks. - * Routes may be nested (if the framework supports nested routes). - */ -export interface RouteNode extends INode { - readonly type: "route"; - readonly children: ChildNode[]; -} - -export interface ComponentNode extends INode { - readonly type: "component"; - readonly parts: ComponentPart[]; - readonly children: ComponentNode[]; -} - -export interface LifecyclePart extends INode { - readonly type: "lifecycle"; - readonly timing: "layout" | "idle"; - readonly setups: Tagged[]; -} - -export interface RefPart extends INode { - readonly type: "ref"; - readonly element: anydom.Element | null; -} - -export interface ModifierPart extends INode { - readonly type: "modifier"; - readonly timing: "layout" | "idle"; - readonly ref: RefPart; -} - -export interface DomResourcePart extends INode { - readonly type: "resource:dom"; - readonly timing: "layout" | "idle"; - readonly reactive: Tagged; -} - -export interface ResourcePart extends INode { - readonly type: "resource"; - readonly reactive: Tagged; -} - -export type ComponentPart = - | LifecyclePart - | RefPart - | ModifierPart - | ResourcePart - | DomResourcePart; diff --git a/packages/universal/interfaces/src/debug/call-stack.ts b/packages/universal/interfaces/src/debug/call-stack.ts new file mode 100644 index 00000000..44b5f792 --- /dev/null +++ b/packages/universal/interfaces/src/debug/call-stack.ts @@ -0,0 +1,24 @@ +export type CallerStackFn = (internal?: number) => CallStack | undefined; + +export interface CallStack { + readonly header: string; + readonly frames: readonly [StackFrame, ...StackFrame[]]; + slice: (n: number) => CallStack | undefined; +} + +export interface StackFrame { + readonly action: string; + readonly module: ParsedModule; + + readonly loc: Loc | undefined; +} + +export interface Loc { + readonly line: number; + readonly column: number | undefined; +} + +export interface ParsedModule { + root?: string | { package: string } | undefined; + path: string; +} diff --git a/packages/universal/interfaces/src/debug/debug-runtime.ts b/packages/universal/interfaces/src/debug/debug-runtime.ts new file mode 100644 index 00000000..f90216c1 --- /dev/null +++ b/packages/universal/interfaces/src/debug/debug-runtime.ts @@ -0,0 +1,22 @@ +import type { Tag, Tagged } from "../protocol.js"; +import type { CallerStackFn, CallStack } from "./call-stack.js"; +import type { DescriptionDetails, DescriptionRuntime } from "./description.js"; + +export interface DebugRuntime { + getUserFacing: ( + description: D + ) => D; + describe: ( + description: DescriptionDetails, + options?: { id: boolean | undefined } | undefined + ) => string; + describeTagged: ( + tagged: Tagged, + options?: { id: boolean | undefined } | undefined + ) => string; + readonly untrackedReadBarrier: ( + barrier: (tag: Tag, stack: CallStack | undefined) => void | never + ) => void; + readonly callerStack: CallerStackFn; + readonly desc: DescriptionRuntime; +} diff --git a/packages/universal/interfaces/src/debug/description.ts b/packages/universal/interfaces/src/debug/description.ts new file mode 100644 index 00000000..d258c955 --- /dev/null +++ b/packages/universal/interfaces/src/debug/description.ts @@ -0,0 +1,116 @@ +import type { ReactiveId, Tag } from "../protocol.js"; +import type { Expand } from "../utils.js"; +import type { CallStack, StackFrame } from "./call-stack.js"; + +export type ReactiveType = + | Expand + | "resource" + | "service" + | "collection" + | "collection:item"; + +export type DescriptionRuntime = ( + type: ReactiveType, + specified?: string | Description | undefined, + // FIXME: speculative inference strategy: if you have a call stack, use the + // action from the caller frame as the default API name + api?: Api | string | undefined +) => Description | undefined; + +export interface Description { + readonly id: ReactiveId; + readonly details: DescriptionDetails; + readonly type: ReactiveType; + readonly caller: CallStack | undefined; + readonly frame: StackFrame | undefined; + readonly isAnonymous: boolean; + + index: (index: number, caller?: CallStack | undefined) => Description; + property: (name: string, caller?: CallStack | undefined) => Description; + key: ( + key: { name: string; key: unknown } | string | number, + caller?: CallStack | undefined + ) => Description; + detail: ( + type: ReactiveType, + name: string, + args?: string[] | CallStack, + caller?: CallStack | undefined + ) => Description; + implementation: ( + type: ReactiveType, + name: string, + reason: string, + caller?: CallStack | undefined + ) => Description; +} + +export interface DescriptionDetails { + readonly id: ReactiveId; + readonly type: ReactiveType; + readonly api?: Api | undefined; + readonly caller: CallStack | undefined; + readonly nesting?: Nesting | undefined; + /** + * The user-specified description, if specified. + */ + readonly specified?: string | undefined; +} + +export type Api = FunctionApi | MethodApi | SimpleFunctionApi; + +export interface SomeApi { + readonly package: string; + readonly module: string; + readonly type: "function" | "method"; +} + +/** + * While it would be nice to reliably have the package and module for all + * functions, we can't always get it. In those situations, we try to infer the + * function name through the call stack, and also allow the user to specify a + * simple string that represents the function. `SimpleFunctionApi` is used to + * represent that. + */ +export interface SimpleFunctionApi { + readonly type: "simple"; + readonly name: string; + readonly caller: CallStack | undefined; +} + +export interface FunctionApi extends SomeApi { + readonly type: "function"; + readonly name: string; +} + +export interface MethodApi extends SomeApi { + readonly type: "method"; + readonly class: string; + readonly placement: "static" | "instance"; +} + +export type Nesting = ChildType & { + readonly parent: DescriptionDetails; +}; + +export type ChildType = + | { + readonly type: "index"; + readonly value: number; + } + | { + readonly type: "property"; + readonly value: string; + } + | { + readonly type: "key"; + readonly value: { name: string; key: unknown }; + } + | { + readonly type: "detail"; + readonly value: { name: string; args: string[] }; + } + | { + readonly type: "implementation"; + readonly value: { name: string; reason: string }; + }; diff --git a/packages/universal/interfaces/src/description.d.ts b/packages/universal/interfaces/src/description.d.ts deleted file mode 100644 index c763ddfe..00000000 --- a/packages/universal/interfaces/src/description.d.ts +++ /dev/null @@ -1,243 +0,0 @@ -import type { ReactiveId } from "./protocol.js"; -import type { Stack, StackFrame, StackFrameDisplayOptions } from "./stack.js"; - -export interface DescriptionArgs { - /** - * An identifier for this description that is stable for the value that this description - * describes. - * - * For example, a `Cell` is allowed to return a new description each time its `[TAG]` symbol - * is read, but the description must have the same `id` each time. - */ - readonly id?: ReactiveId | undefined; - - /** - * The type is a high-level categorization from the perspective of Starbeam. It is used in - * developer tools to decide how to render the description. - */ - type: DescriptionType; - /** - * The {@linkcode api} is the user-facing, public API entry point that the developer used to - * construct the thing that this description is describing. For example, the `useSetup` hook in - * `@starbeam/react` has the type "resource" and the api "useStarbeam". - */ - api?: string | ApiDetails | undefined; - /** - * An optional description, as provided by the end user. Each instance of an abstraction like - * `useSetup` should have a different description (this is the distinction between `api` and - * `fromUser`). - */ - fromUser?: DescriptionDetails | Description | undefined; - - internal?: - | { - reason: string; - userFacing: Description; - } - | undefined; - - stack?: Stack | undefined; -} - -export interface DescriptionDescribeOptions extends StackFrameDisplayOptions { - source?: boolean | undefined; - id?: boolean | undefined; - color?: boolean | undefined; -} - -export type DescriptionKey = string | number; - -export interface Description extends DescriptionArgs { - readonly name: string; - readonly fullName: string; - readonly id: ReactiveId; - readonly type: DescriptionType; - readonly api: string | ApiDetails | undefined; - readonly userFacing: Description; - readonly parts: DescriptionParts; - - // TODO: Figure out how to reliably infer this in debug builds. Since people - // use a lot of different dev-time tools, it we may need to insert the - // information when we build the debug builds (it may not be possible to infer - // it from stack traces reliably).formula - forApi: (api: string | ApiDetails) => Description; - - method: ( - id: ReactiveId | symbol, - name: string, - args?: DescriptionArgument[] - ) => Description; - /** - * An index is an integer property access on an object. This access must refer - * to a stable cell for the lifetime of the object referred to by the parent - * description. - */ - index: (index: number) => Description; - /** - * A property is a string property access on an object. This access must refer - * to a stable cell for the lifetime of the object referred to by the parent - * description. - */ - property: (name: string) => Description; - /** - * A `key` is like a property access, but the name is not a string property - * access. For example, the key passed to `.get` on a map is a key and not a - * property, because `.get` is not a property access. Unlike `detail`, a key - * refers to something that the user actually typed in their code. - * - * If the key isn't a string or number, the code creating the description - * should convert it to a string for display purposes. If that process is - * lossy (i.e. multiple keys produce the same string), the code creating the - * description must pass an `id` option that so that the description refers to - * a stable cell backed by the key. - */ - key: ( - name: DescriptionKey, - options?: { id?: ReactiveId; note?: string } - ) => Description; - /** - * A detail is a representation of a *public* part of a value. Unlike - * `.property` or `.index`, the user will not have physically typed the name - * of the detail in the code. Unlike `.implementation`, a *detail* is a part - * of the public API of the value and can be understood by lay users. - * - * If an explicit id is not passed to `.detail`, a detail's name must refer to - * a stable cell for the lifetime of the object referred to by the parent - * description. - */ - detail: ( - name: string, - args?: string[] | { args?: string[]; note?: string; id?: ReactiveId } - ) => Description; - implementation: ( - id: ReactiveId | symbol, - options?: { - reason?: string; - userFacing?: Description; - stack?: Stack; - } - ) => Description; - - /** - * Mark the current description as an implementation detail. This allows the implementation detail - * to refer to a user-facing concept (such as `.detail` or `.property`). - */ - asImplementation: (options?: { reason: string }) => Description; - - withStack: (stack: Stack, id: ReactiveId | symbol) => Description; - withId: (id?: ReactiveId) => Description; - - describe: (options?: DescriptionDescribeOptions) => string; - readonly frame: StackFrame | undefined; -} - -export type MarkerType = - | "collection:key-value" - | "collection:value" - | "collection:value:entry" - | "collection:key-value:entry"; - -export type ValueType = - | "implementation" - // represents a value that is not Starbeam-reactive, but is reactive according to the rules of the - // external framework embedding Starbeam (e.g. React) - | "external" - // represents a renderer value - | "renderer" - // represents a value that delegates to another reactive value - | "delegate" - | "static" - | "cell" - | "collection" - | "formula" - | "resource" - | "service" - | "variants"; - -export type BlueprintType = - | "blueprint:reactive" - | "blueprint:resource" - | "blueprint:service"; - -/** DescriptionType is `erased` in production */ -export type DescriptionType = MarkerType | ValueType | BlueprintType | "erased"; - -export interface MemberDescription { - type: "member"; - kind: "index" | "property" | "key"; - note?: string | undefined; - parent: Description; - name: string | number; -} - -export interface DetailDescription { - type: "detail"; - args?: string[] | undefined; - note?: string | undefined; - parent: Description; - name: string; -} - -export type DescriptionArgument = string | number | boolean; - -interface MethodDescription { - type: "method"; - parent: Description; - name: string; - args?: DescriptionArgument[] | undefined; -} - -interface ValueDescription { - type: "value"; - name: string; -} - -interface AnonymousDescription { - type: "anonymous"; -} - -export type DescriptionDetails = - | string - | MemberDescription - | MethodDescription - | DetailDescription; - -export type DetailsPart = - | MemberDescription - | MethodDescription - | DetailDescription - | ValueDescription - | AnonymousDescription; - -export interface ApiDetails { - package?: string | undefined; - module?: string | undefined; - // default is allowed here - name?: string | undefined; - method?: - | { - type: "static"; - name: string; - } - | { - type: "instance"; - name: string; - } - | undefined; -} - -export interface InternalDescription { - reason?: string | undefined; - userFacing: Description; -} - -export interface DescriptionParts { - readonly type: DescriptionType; - readonly id: ReactiveId; - readonly api: ApiDetails | undefined; - readonly details: DetailsPart; - readonly userFacing: Description; - readonly internal?: InternalDescription | undefined; - readonly frame: StackFrame | undefined; - readonly stack: string | undefined; -} diff --git a/packages/universal/interfaces/src/diff.d.ts b/packages/universal/interfaces/src/diff.d.ts deleted file mode 100644 index de8db153..00000000 --- a/packages/universal/interfaces/src/diff.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Diff { - readonly add: Set; - readonly remove: Set; -} diff --git a/packages/universal/interfaces/src/frame.d.ts b/packages/universal/interfaces/src/frame.d.ts deleted file mode 100644 index 248d8770..00000000 --- a/packages/universal/interfaces/src/frame.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { UNINITIALIZED } from "@starbeam/shared"; - -import type { Description } from "./description.js"; -import type { FormulaTag, Tagged } from "./protocol.js"; - -export interface ValidFrame { - readonly status: "valid"; - readonly value: T; -} - -export interface InvalidFrame { - readonly status: "invalid"; -} - -export type FrameValidation = ValidFrame | InvalidFrame; - -export interface Frame<_T = unknown> - extends Tagged { - readonly description: Description; - - validate: () => FrameValidation>; -} diff --git a/packages/universal/interfaces/src/protocol.d.ts b/packages/universal/interfaces/src/protocol.ts similarity index 76% rename from packages/universal/interfaces/src/protocol.d.ts rename to packages/universal/interfaces/src/protocol.ts index c1165357..83719022 100644 --- a/packages/universal/interfaces/src/protocol.d.ts +++ b/packages/universal/interfaces/src/protocol.ts @@ -1,51 +1,26 @@ import type { TAG } from "@starbeam/shared"; -import type { Description } from "./description.js"; +import type { CallStack } from "./debug/call-stack.js"; +import type { Description } from "./debug/description.js"; import type { UpdateOptions } from "./runtime.js"; -import type { Stack } from "./stack.js"; import type { Timestamp } from "./timestamp.js"; export type ReactiveId = number | string | ReactiveId[]; -export interface AbstractTag { - readonly type: TagType; - readonly description: Description; +export type TagSet = ReadonlySet; - /** - * This flag is false in formula tags, when the tag hasn't been computed yet. - * This avoids subscribing to a formula without computing its value, which is - * a violation of the tag contract. - */ - readonly initialized: boolean; -} - -export type List = Iterable | T[] | readonly T[]; - -export class TagMethods { - readonly id: ReactiveId; +export declare class TagMethods { readonly lastUpdated: Timestamp; readonly dependencies: () => readonly CellTag[]; - readonly description: Description; - readonly subscriptionTargets: readonly SubscriptionTarget[]; - match(matcher: Matcher): Tag; } -export type ExhaustiveMatcher = { - [P in TagType]: (tag: Extract) => T; -}; - -export interface DefaultMatcher extends Partial> { - default: (internals: Tag) => T; -} - -export type Matcher = ExhaustiveMatcher | DefaultMatcher; - /** * Cell is the fundamental mutable reactive value. All subscriptions in Starbeam are ultimately * subscriptions to cells, and all mutations in Starbeam are ultimately mutations to cells. */ -export interface CellTag extends AbstractTag, TagMethods { +export interface CellTag extends TagMethods { readonly type: "cell"; + readonly description: Description | undefined; readonly lastUpdated: Timestamp; isFrozen: () => boolean; freeze: () => void; @@ -64,8 +39,23 @@ export interface CellTag extends AbstractTag, TagMethods { * notified of a change to the composite's children, it removes subscriptions from any stale * dependencies and adds subscriptions to any new dependencies. */ -export interface FormulaTag extends AbstractTag, TagMethods { +export interface FormulaTag extends TagMethods { readonly type: "formula"; + readonly description: Description | undefined; + + /** + * This flag starts out as false, when the formula hasn't been computed yet. + * Any subscriptions to an uninitialized formula will be deferred until the + * formula is initialized. + */ + readonly initialized: boolean; + + /** + * This method should be called by the formula's implementation after it is + * first computed, but before the timeline's `update` method is called. + */ + markInitialized: () => void; + /** * The current children of this formula. Note that "no children" does not * necessarily mean that the formula is static, because a formula has no @@ -75,7 +65,7 @@ export interface FormulaTag extends AbstractTag, TagMethods { * attempting to read the children if they plan to rely on the absence of * children as a strong indicator of staticness. */ - children: () => readonly Tag[]; + children: () => ReadonlySet; } /** @@ -87,8 +77,9 @@ export interface FormulaTag extends AbstractTag, TagMethods { * targets. This means that delegates don't need to know when their value changes, and don't need to * notify the timeline when their targets change. */ -export interface DelegateTag extends AbstractTag, TagMethods { +export interface DelegateTag extends TagMethods { readonly type: "delegate"; + readonly description: Description | undefined; readonly targets: readonly Tag[]; } @@ -104,8 +95,9 @@ export interface DelegateTag extends AbstractTag, TagMethods { * TODO: Do we need a separate fundamental type for pollable formulas, which can get new * dependencies even if they never invalidate? */ -export interface StaticTag extends AbstractTag, TagMethods { +export interface StaticTag extends TagMethods { readonly type: "static"; + readonly description: Description | undefined; } /** @@ -118,9 +110,15 @@ export interface StaticTag extends AbstractTag, TagMethods { * they are, and that generality breaks system invariants derived from value composition. */ export type Tag = CellTag | FormulaTag | DelegateTag | StaticTag; + +/** + * Cells and formulas can be subscribed to directly. + * + * A subscription to a formula is a dynamic subscription to its current dependencies. + * A subscription to a delegate is equivalent to subscribing to its (stable) targets. + * A subscription to a static is equivalent to subscribing to nothing. + */ export type SubscriptionTarget = CellTag | FormulaTag; -export type TagType = Tag["type"]; -export type SpecificTag = Extract; /** * A `Tagged` object is a reactive object that has a `Tag` (which is used to @@ -143,7 +141,7 @@ export interface Tagged { export interface ReactiveValue extends Tagged { - read: (stack?: Stack) => T; + read: (stack?: CallStack) => T; } export interface Reactive extends ReactiveValue { @@ -155,10 +153,10 @@ export interface TaggedReactive readonly current: T; } -export interface ReactiveCell extends Reactive { +export interface ReactiveCell extends ReactiveValue { current: T; } -export interface ReactiveFormula extends Reactive { +export interface ReactiveFormula extends ReactiveValue { readonly current: T; } diff --git a/packages/universal/interfaces/src/runtime.d.ts b/packages/universal/interfaces/src/runtime.ts similarity index 58% rename from packages/universal/interfaces/src/runtime.d.ts rename to packages/universal/interfaces/src/runtime.ts index 6647bed0..d27e5158 100644 --- a/packages/universal/interfaces/src/runtime.d.ts +++ b/packages/universal/interfaces/src/runtime.ts @@ -1,35 +1,23 @@ -import type { Unsubscribe } from "./aliases.js"; +import type { CallStack } from "./debug/call-stack.js"; +import type { DebugRuntime } from "./debug/debug-runtime.js"; import type { CellTag, FormulaTag, Tag } from "./protocol.js"; -import type { Stack as CallStack } from "./stack.js"; import type { Timestamp } from "./timestamp.js"; - -/** - * @deprecated - */ -export interface DeprecatedTimeline { - bumpCell: (cell: CellTag, caller: CallStack) => Timestamp; - didConsumeCell: (cell: CellTag, caller: CallStack) => void; -} +import type { Unsubscribe } from "./utils.js"; export interface Runtime { - callerStack: () => CallStack; readonly subscriptions: SubscriptionRuntime; readonly autotracking: AutotrackingRuntime; - readonly debug: DebugRuntime; + readonly debug: DebugRuntime | undefined; } +export type NotifyReady = (internals: CellTag) => void; + export interface SubscriptionRuntime { subscribe: (target: Tag, ready: NotifyReady) => Unsubscribe; - bump: (cell: CellTag) => { revision: Timestamp; notify: () => void }; + bump: (cell: CellTag, update: (revision: Timestamp) => void) => void; update: (formula: FormulaTag) => void; } -export interface DebugRuntime { - untrackedReadBarrier: ( - barrier: (tag: Tag, stack: CallStack) => void | never - ) => void; -} - export type ActiveFrame = () => Set; export interface AutotrackingRuntime { @@ -44,7 +32,7 @@ export interface ActiveRuntimeFrame { export type RuntimeFrame = object; export interface UpdateOptions { - readonly caller: CallStack; + readonly caller: CallStack | undefined; readonly runtime: Runtime; } diff --git a/packages/universal/interfaces/src/stack.d.ts b/packages/universal/interfaces/src/stack.d.ts deleted file mode 100644 index 7ea42db8..00000000 --- a/packages/universal/interfaces/src/stack.d.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface Stack { - readonly caller: StackFrame | undefined; - readonly stack: string; -} - -export interface StackFrameDisplayOptions { - readonly root?: string; - readonly roots?: Record; - /** - * display the entire stack trace - */ - readonly complete?: boolean; -} - -export interface StackFrame { - readonly starbeamCaller: - | { package: string; api?: string | undefined } - | undefined; - - /** - * A link to the file/line/column that this stack frame represents, in a format suitable to be - * used in console.log()s in browser devtools. - */ - link: (options?: StackFrameDisplayOptions | undefined) => string; - - /** - * A displayable representation of the stack frame. - */ - display: (options?: StackFrameDisplayOptions | undefined) => string; - - parts: (options?: StackFrameDisplayOptions | undefined) => DisplayParts; -} - -export interface DisplayRoot { - name?: string | undefined; - prefix: string; -} - -export interface Loc { - line: number; - column?: number | undefined; -} - -export interface DisplayParts { - readonly path: string; - readonly root: DisplayRoot | undefined; - readonly action: string | undefined; - readonly loc: Loc | undefined; - - display: () => string; -} diff --git a/packages/universal/interfaces/src/timestamp.d.ts b/packages/universal/interfaces/src/timestamp.ts similarity index 100% rename from packages/universal/interfaces/src/timestamp.d.ts rename to packages/universal/interfaces/src/timestamp.ts diff --git a/packages/universal/interfaces/src/utils.d.ts b/packages/universal/interfaces/src/utils.d.ts deleted file mode 100644 index 1f4c4f9f..00000000 --- a/packages/universal/interfaces/src/utils.d.ts +++ /dev/null @@ -1 +0,0 @@ -export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; diff --git a/packages/universal/interfaces/src/utils.ts b/packages/universal/interfaces/src/utils.ts new file mode 100644 index 00000000..9035c936 --- /dev/null +++ b/packages/universal/interfaces/src/utils.ts @@ -0,0 +1,7 @@ +export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; +export type Unsubscribe = () => void; + +export interface Diff { + readonly add: Set; + readonly remove: Set; +} diff --git a/packages/universal/interfaces/tsconfig.json b/packages/universal/interfaces/tsconfig.json index 50c49173..45022e0e 100644 --- a/packages/universal/interfaces/tsconfig.json +++ b/packages/universal/interfaces/tsconfig.json @@ -9,5 +9,5 @@ "types": ["../../env"] }, "exclude": ["dist/**/*"], - "include": ["index.d.ts", "./src/**/*.ts"] + "include": ["index.ts", "./src/**/*.ts", "./src/**/*.d.ts"] } diff --git a/packages/universal/modifier/package.json b/packages/universal/modifier/package.json index 7e2d0d75..3dfaa286 100644 --- a/packages/universal/modifier/package.json +++ b/packages/universal/modifier/package.json @@ -26,6 +26,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^", "@starbeam/universal": "workspace:^", diff --git a/packages/universal/modifier/src/modifier.ts b/packages/universal/modifier/src/modifier.ts index 7db028e7..b46f35c4 100644 --- a/packages/universal/modifier/src/modifier.ts +++ b/packages/universal/modifier/src/modifier.ts @@ -1,6 +1,6 @@ import type { anydom } from "@domtree/flavors"; -import { type Description, REUSE_ID } from "@starbeam/debug"; -import type { Tagged } from "@starbeam/interfaces"; +import type { Description, Tagged } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; import { DelegateTag, getTag } from "@starbeam/tags"; import { Cell } from "@starbeam/universal"; @@ -27,9 +27,11 @@ export function ElementPlaceholder( ): ElementPlaceholder { const ref = Object.create(null) as object; const elementCell = Cell(UNINITIALIZED, { - description: description.implementation(REUSE_ID, { - reason: "element cell", - }), + description: description.implementation( + "cell", + "element", + "ref placeholder" + ), }); REFS.set(ref, elementCell); @@ -42,7 +44,7 @@ export function ElementPlaceholder( verify( value, (anyElement): anyElement is E => anyElement instanceof type, - expected(`A ref (${description.describe()})`) + expected(`A ref (${RUNTIME.debug?.describe(description) ?? "unknown"})`) .toBe(`initialized with an instance of ${type.name}`) .butGot(() => `an instance of ${value.constructor.name}`) ); diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 31450b6f..96cd5e9c 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -10,12 +10,11 @@ export { export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; export { type FormulaFn, isFormulaFn } from "./src/primitives/utils.js"; -export { defineRuntime, getRuntime } from "./src/runtime.js"; +export { defineRuntime, RUNTIME } from "./src/runtime.js"; export { intoReactive, isReactive, isTagged, - isTaggedReactive, read, type ReadValue, } from "./src/utils.js"; diff --git a/packages/universal/reactive/package.json b/packages/universal/reactive/package.json index dacd6cf8..51d73b1c 100644 --- a/packages/universal/reactive/package.json +++ b/packages/universal/reactive/package.json @@ -19,7 +19,6 @@ }, "dependencies": { "@starbeam/core-utils": "workspace:^", - "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^", "@starbeam/tags": "workspace:^" diff --git a/packages/universal/reactive/src/primitives/base.ts b/packages/universal/reactive/src/primitives/base.ts index c9f5b297..85b705bb 100644 --- a/packages/universal/reactive/src/primitives/base.ts +++ b/packages/universal/reactive/src/primitives/base.ts @@ -1,8 +1,8 @@ import { readonly } from "@starbeam/core-utils"; -import type { Stack, Tag } from "@starbeam/interfaces"; +import type { CallStack, Tag } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { getRuntime } from "../runtime.js"; +import { RUNTIME } from "../runtime.js"; export abstract class ReactivePrimitive { declare readonly [TAG]: T; @@ -11,9 +11,9 @@ export abstract class ReactivePrimitive { readonly(this, TAG, tag); } - abstract read(caller: Stack): V; + abstract read(caller?: CallStack): V; get current(): V { - return this.read(getRuntime().callerStack()); + return this.read(RUNTIME.callerStack?.()); } } diff --git a/packages/universal/reactive/src/primitives/cached.ts b/packages/universal/reactive/src/primitives/cached.ts index b9696ba3..a3eff56a 100644 --- a/packages/universal/reactive/src/primitives/cached.ts +++ b/packages/universal/reactive/src/primitives/cached.ts @@ -1,7 +1,10 @@ -import { callerStack, Desc, type Description } from "@starbeam/debug"; -import type { ReactiveFormula } from "@starbeam/interfaces"; +import type { + Description, + FormulaTag, + ReactiveFormula, +} from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { FormulaTag } from "@starbeam/tags"; +import { createFormulaTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; import type { Formula } from "./formula.js"; @@ -27,7 +30,10 @@ class FormulaImpl implements ReactiveFormula { options?: SugaryPrimitiveOptions ): FormulaFn => { const { description } = toOptions(options); - const formula = new FormulaImpl(compute, Desc("formula", description)); + const formula = new FormulaImpl( + compute, + RUNTIME.debug?.desc("formula", description) + ); return WrapFn(formula); }; @@ -36,20 +42,20 @@ class FormulaImpl implements ReactiveFormula { readonly #compute: () => T; #last: Last | null; - private constructor(compute: () => T, description: Description) { + private constructor(compute: () => T, description: Description | undefined) { this.#last = null; this.#compute = compute; - this[TAG] = FormulaTag.create(description, () => { - if (this.#last === null) return []; + this[TAG] = createFormulaTag(description, () => { + if (this.#last === null) return new Set(); return this.#last.formula.children(); }); } get current(): T { - return this.read(callerStack()); + return this.read(RUNTIME.callerStack?.()); } - read(_caller = callerStack()): T { + read(_caller = RUNTIME.callerStack?.()): T { const value = this.#evaluate(); RUNTIME.autotracking.consume(this[TAG]); return value; diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index 500f42e7..80d72722 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -1,15 +1,13 @@ import { readonly } from "@starbeam/core-utils"; -import type * as Debug from "@starbeam/debug"; -import { Desc } from "@starbeam/debug"; import type { CellTag as ICellTag, - Expand, + Description, ReactiveCell, } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { CellTag } from "@starbeam/tags"; +import { createCellTag } from "@starbeam/tags"; -import { getRuntime } from "../runtime.js"; +import { RUNTIME } from "../runtime.js"; import { type DescriptionOption, isDescriptionOption, @@ -22,7 +20,7 @@ export class CellImpl implements ReactiveCell { options?: CellOptions | DescriptionOption ): Cell => { const { description, equals = Object.is } = toCellOptions(options); - return new CellImpl(value, equals, Desc("cell", description)); + return new CellImpl(value, equals, RUNTIME.Desc?.("cell", description)); }; #value: T; @@ -32,36 +30,37 @@ export class CellImpl implements ReactiveCell { private constructor( value: T, equality: Equality, - description: Debug.Description + description: Description | undefined ) { this.#value = value; this.#equals = equality; - readonly(this, TAG, CellTag.create(description)); + readonly(this, TAG, createCellTag(description)); } get current(): T { - return this.read(getRuntime().callerStack()); + return this.read(RUNTIME.callerStack?.()); } set current(value: T) { - this.set(value, getRuntime().callerStack()); + this.set(value, RUNTIME.callerStack?.()); } - read(_caller = getRuntime().callerStack()): T { - getRuntime().autotracking.consume(this[TAG]); + read(_caller = RUNTIME.callerStack?.()): T { + RUNTIME.autotracking.consume(this[TAG]); return this.#value; } - set(value: T, caller = getRuntime().callerStack()) { + set(value: T, caller = RUNTIME.callerStack?.()): boolean { if (this.#equals(value, this.#value)) { return false; } this.#value = value; - this[TAG].update({ caller, runtime: getRuntime() }); + this[TAG].update({ caller, runtime: RUNTIME }); + return true; } - update(updater: (prev: T) => T, caller = getRuntime().callerStack()) { + update(updater: (prev: T) => T, caller = RUNTIME.callerStack?.()) { this.set(updater(this.#value), caller); } diff --git a/packages/universal/reactive/src/primitives/delegate.ts b/packages/universal/reactive/src/primitives/delegate.ts index 4cf64c74..edc4b15c 100644 --- a/packages/universal/reactive/src/primitives/delegate.ts +++ b/packages/universal/reactive/src/primitives/delegate.ts @@ -1,25 +1,29 @@ -import { getter, method, readonly } from "@starbeam/core-utils"; -import type { Stack } from "@starbeam/debug"; -import { callerStack, type Description } from "@starbeam/debug"; +import { defMethod, getter, readonly } from "@starbeam/core-utils"; +import type { CallStack, Description } from "@starbeam/interfaces"; import type * as interfaces from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { DelegateTag, getTag, taggedDescription } from "@starbeam/tags"; +import { createDelegateTag, getDescription, getTag } from "@starbeam/tags"; + +import { RUNTIME } from "../runtime.js"; export function Wrap( reactive: U, value: T, - desc?: Description | string + desc?: Description | string | undefined ): T & U { readonly( value, TAG, - DelegateTag.create(delegateDesc(reactive, desc), [getTag(reactive)]) + createDelegateTag(delegateDesc(reactive, desc), [getTag(reactive)]) ); - method(value, "read", (caller: Stack = callerStack()) => - reactive.read(caller) + defMethod( + value, + "read", + (caller: CallStack | undefined = RUNTIME.callerStack?.()) => + reactive.read(caller) ); - getter(value, "current", () => reactive.read(callerStack())); + getter(value, "current", () => reactive.read(RUNTIME.callerStack?.())); return value as T & U; } @@ -27,13 +31,13 @@ export function Wrap( function delegateDesc( to: interfaces.Tagged | interfaces.Tagged[], desc?: string | Description -): Description { +): Description | undefined { if (Array.isArray(to)) { return desc as Description; } else if (typeof desc === "string") { - return taggedDescription(to).detail(desc); + return getDescription(to)?.detail("delegate", desc); } else if (desc === undefined) { - return taggedDescription(to).detail("{delegate}"); + return getDescription(to)?.detail("delegate", "anonymous"); } else { return desc; } diff --git a/packages/universal/reactive/src/primitives/formula-lifecycle.ts b/packages/universal/reactive/src/primitives/formula-lifecycle.ts index 13500764..c53d7d31 100644 --- a/packages/universal/reactive/src/primitives/formula-lifecycle.ts +++ b/packages/universal/reactive/src/primitives/formula-lifecycle.ts @@ -1,27 +1,32 @@ -import { Desc } from "@starbeam/debug"; import type { ActiveFrame, Description, Expand, + Tag, Timestamp, } from "@starbeam/interfaces"; -import type { Tag } from "@starbeam/interfaces"; -import { NOW, TagUtils } from "@starbeam/tags"; +import { lastUpdated, NOW } from "@starbeam/tags"; -import { getRuntime } from "../runtime.js"; +import { RUNTIME } from "../runtime.js"; import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; export class InitializingFormulaImpl { static start = (options?: SugaryPrimitiveOptions): InitializingFormula => { const { description } = toOptions(options); - const active = getRuntime().autotracking.start(); - return new InitializingFormulaImpl(active, Desc("formula", description)); + const active = RUNTIME.autotracking.start(); + return new InitializingFormulaImpl( + active, + RUNTIME.Desc?.("formula", description) + ); }; readonly #active: ActiveFrame; - readonly #description: Description; + readonly #description: Description | undefined; - private constructor(active: () => Set, description: Description) { + private constructor( + active: () => Set, + description: Description | undefined + ) { this.#active = active; this.#description = description; } @@ -49,7 +54,7 @@ class FinalizedFormulaImpl { } isStale(): boolean { - return TagUtils.lastUpdatedIn(this.#children).gt(this.#lastValidated); + return lastUpdated(...this.#children).gt(this.#lastValidated); } children(): Set { @@ -57,7 +62,7 @@ class FinalizedFormulaImpl { } update(): InitializingFormula { - const done = getRuntime().autotracking.start(); + const done = RUNTIME.autotracking.start(); return { done: () => { diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts index ccb53696..d4a9e15e 100644 --- a/packages/universal/reactive/src/primitives/formula.ts +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -1,12 +1,12 @@ -import { Desc } from "@starbeam/debug"; import type { Description, Expand, ReactiveFormula, - Tag, + TagSet, } from "@starbeam/interfaces"; +import type { FormulaTag } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { FormulaTag } from "@starbeam/tags"; +import { createFormulaTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; import { ReactivePrimitive } from "./base.js"; @@ -23,20 +23,23 @@ export class FormulaImpl { static create = (compute: () => T, options?: SugaryPrimitiveOptions) => { const { description } = toOptions(options); - const formula = new FormulaImpl(compute, Desc("formula", description)); + const formula = new FormulaImpl( + compute, + RUNTIME.Desc?.("formula", description) + ); return WrapFn(formula); }; #compute: () => T; - #children = new Set(); + #children: TagSet = new Set(); - private constructor(compute: () => T, description: Description) { - super(FormulaTag.create(description, () => this.#children)); + private constructor(compute: () => T, description: Description | undefined) { + super(createFormulaTag(description, () => this.#children)); this.#compute = compute; } - read(_caller = RUNTIME.callerStack()): T { + read(_caller = RUNTIME.callerStack?.()): T { const { value, tags } = RUNTIME.evaluate(this.#compute); this.#children = tags; diff --git a/packages/universal/reactive/src/primitives/marker.ts b/packages/universal/reactive/src/primitives/marker.ts index 2cf83487..131cac0b 100644 --- a/packages/universal/reactive/src/primitives/marker.ts +++ b/packages/universal/reactive/src/primitives/marker.ts @@ -1,38 +1,38 @@ import { readonly } from "@starbeam/core-utils"; -import { Desc, type Description } from "@starbeam/debug"; import { type CellTag as ICellTag, + type Description, type Expand, type Tagged, } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { CellTag } from "@starbeam/tags"; +import { createCellTag } from "@starbeam/tags"; -import { getRuntime } from "../runtime.js"; +import { RUNTIME } from "../runtime.js"; import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; class MarkerImpl implements Tagged { static create(this: void, options?: SugaryPrimitiveOptions): MarkerImpl { const { description } = toOptions(options); - return new MarkerImpl(Desc("cell", Desc("cell", description))); + return new MarkerImpl(RUNTIME.Desc?.("cell", description)); } declare readonly [TAG]: ICellTag; - private constructor(description: Description) { - readonly(this, TAG, CellTag.create(description)); + private constructor(description: Description | undefined) { + readonly(this, TAG, createCellTag(description)); } - read(_caller = getRuntime().callerStack()): void { - getRuntime().autotracking.consume(this[TAG]); + read(_caller = RUNTIME.callerStack?.()): void { + RUNTIME.autotracking.consume(this[TAG]); } freeze(): void { this[TAG].freeze(); } - mark(caller = getRuntime().callerStack()): void { - this[TAG].update({ caller, runtime: getRuntime() }); + mark(caller = RUNTIME.callerStack?.()): void { + this[TAG].update({ caller, runtime: RUNTIME }); } } diff --git a/packages/universal/reactive/src/primitives/static.ts b/packages/universal/reactive/src/primitives/static.ts index d76e075f..ece3647e 100644 --- a/packages/universal/reactive/src/primitives/static.ts +++ b/packages/universal/reactive/src/primitives/static.ts @@ -1,9 +1,9 @@ -import type * as Debug from "@starbeam/debug"; -import { Desc } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; +import type { Description } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import { StaticTag } from "@starbeam/tags"; +import { createStaticTag } from "@starbeam/tags"; +import { RUNTIME } from "../runtime.js"; import type { PrimitiveOptions } from "./utils.js"; export class StaticImpl @@ -13,15 +13,15 @@ export class StaticImpl value: T, { description }: PrimitiveOptions = {} ): StaticImpl => { - return new StaticImpl(value, Desc("static", description)); + return new StaticImpl(value, RUNTIME.Desc?.("static", description)); }; readonly #value: T; readonly [TAG]: interfaces.StaticTag; - private constructor(value: T, description: Debug.Description) { + private constructor(value: T, description: Description | undefined) { this.#value = value; - this[TAG] = StaticTag.create(description); + this[TAG] = createStaticTag(description); } get current(): T { diff --git a/packages/universal/reactive/src/primitives/utils.ts b/packages/universal/reactive/src/primitives/utils.ts index 8ae34ff4..635b9837 100644 --- a/packages/universal/reactive/src/primitives/utils.ts +++ b/packages/universal/reactive/src/primitives/utils.ts @@ -1,7 +1,11 @@ -import type { Description } from "@starbeam/debug"; -import type { ReactiveValue, Tag, TaggedReactive } from "@starbeam/interfaces"; +import type { + Description, + ReactiveValue, + Tag, + TaggedReactive, +} from "@starbeam/interfaces"; +import type { FormulaTag } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; -import type { FormulaTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; @@ -55,7 +59,7 @@ export function WrapFn(formula: ReactiveValue): FormulaFn { } const fn = (): T => { - return formula.read(RUNTIME.callerStack()); + return formula.read(RUNTIME.callerStack?.()); }; Object.defineProperties(fn, { diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index dead5662..8e94cb80 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -1,8 +1,9 @@ import type { AutotrackingRuntime, + CallerStackFn, DebugRuntime, + DescriptionRuntime, Runtime, - Stack, SubscriptionRuntime, Tag, } from "@starbeam/interfaces"; @@ -15,11 +16,11 @@ export function defineRuntime(runtime: Runtime): void { CONTEXT.runtime = runtime; } -export function getRuntime(): Runtime { +function getRuntime(): Runtime { if (import.meta.env.DEV) { if (CONTEXT.runtime === null) { throw Error( - "@starbeam/reactive requires a reactive runtime, but no runtime was registered (did you try to use @starbeam/reactive without @starbeam/universal?)" + "@starbeam/reactive requires a reactive runtime, but no runtime was registered (did you try to use @starbeam/reactive without @starbeam/runtime or @starbeam/universal?)" ); } } @@ -28,8 +29,12 @@ export function getRuntime(): Runtime { } class RuntimeImpl implements Runtime { - callerStack(): Stack { - return getRuntime().callerStack(); + get Desc(): DescriptionRuntime | undefined { + return getRuntime().debug?.desc ?? undefined; + } + + get callerStack(): CallerStackFn | undefined { + return getRuntime().debug?.callerStack; } get subscriptions(): SubscriptionRuntime { @@ -40,7 +45,7 @@ class RuntimeImpl implements Runtime { return getRuntime().autotracking; } - get debug(): DebugRuntime { + get debug(): DebugRuntime | undefined { return getRuntime().debug; } diff --git a/packages/universal/reactive/src/utils.ts b/packages/universal/reactive/src/utils.ts index 09d2c585..649db7e5 100644 --- a/packages/universal/reactive/src/utils.ts +++ b/packages/universal/reactive/src/utils.ts @@ -1,10 +1,9 @@ -import type * as Debug from "@starbeam/debug"; -import { callerStack, Desc } from "@starbeam/debug"; import type * as interfaces from "@starbeam/interfaces"; -import type { TagType } from "@starbeam/interfaces"; +import type { Description, Tag, TaggedReactive } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { Static } from "./primitives/static.js"; +import { RUNTIME } from "./runtime.js"; export type Reactive = interfaces.Reactive; @@ -25,20 +24,12 @@ export function isReactive( return is(value) && hasRead(value); } -export function isTaggedReactive( - this: void, - value: unknown, - tag: Type -): value is interfaces.TaggedReactive, T> { - return is(value) && value[TAG].type === tag && hasRead(value); -} - export type ReadValue = T extends Reactive ? R : T; export function read( this: void, value: T, - caller = callerStack() + caller = RUNTIME.callerStack?.() ): ReadValue { if (is(value) && hasRead(value)) { return value.read(caller) as ReadValue; @@ -50,12 +41,14 @@ export function read( export function intoReactive( this: void, value: T | Reactive, - description?: string | Debug.Description + description?: string | Description ): Reactive { if (isReactive(value)) { return value; } else { - return Static(value, { description: Desc("static", description) }); + return Static(value, { + description: RUNTIME.Desc?.("static", description), + }); } } diff --git a/packages/universal/resource/src/api.ts b/packages/universal/resource/src/api.ts index 9aa4cf00..1adb5008 100644 --- a/packages/universal/resource/src/api.ts +++ b/packages/universal/resource/src/api.ts @@ -1,5 +1,4 @@ -import type { Description } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/interfaces"; +import type { Description, Reactive } from "@starbeam/interfaces"; import type { FormulaFn, ReadValue } from "@starbeam/reactive"; import { ResourceBlueprintImpl, type UseOptions } from "./resource.js"; diff --git a/packages/universal/resource/src/resource-list.ts b/packages/universal/resource/src/resource-list.ts index ee0dd920..dda2553c 100644 --- a/packages/universal/resource/src/resource-list.ts +++ b/packages/universal/resource/src/resource-list.ts @@ -1,4 +1,5 @@ -import { Desc, type Description } from "@starbeam/debug"; +import type { Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import { LIFETIME } from "@starbeam/runtime"; import { @@ -20,7 +21,9 @@ export function ResourceList( description?: string | Description; } ): ResourceBlueprint[], void> { - const resources = new ResourceMap(Desc("collection", description)); + const resources = new ResourceMap( + RUNTIME.Desc?.("collection", description) + ); return Resource((_run, _metadata, lifetime) => { const result: Resource[] = []; @@ -48,9 +51,9 @@ type InternalMap = Map; lifetime: object }>; class ResourceMap { readonly #map: InternalMap = new Map(); - readonly #description: Description; + readonly #description: Description | undefined; - constructor(description: Description) { + constructor(description: Description | undefined) { this.#description = description; } @@ -69,7 +72,11 @@ class ResourceMap { const newResource = use(resource, { lifetime, metadata: options.metadata, - description: this.#description.key(String(key)), + description: this.#description?.key( + typeof key === "object" + ? { key: key.key, name: String(key.description) } + : key + ), }); this.#map.set(key, { resource: newResource, lifetime }); return newResource; diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index 780c0035..20516ada 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -1,6 +1,11 @@ -import { Desc, DisplayStruct } from "@starbeam/debug"; +import { DisplayStruct } from "@starbeam/core-utils"; import type { Description } from "@starbeam/interfaces"; -import { CachedFormula, read, type ReadValue } from "@starbeam/reactive"; +import { + CachedFormula, + read, + type ReadValue, + RUNTIME, +} from "@starbeam/reactive"; import { LIFETIME, TAG } from "@starbeam/runtime"; import type { IntoResourceBlueprint, Resource } from "./api.js"; @@ -83,13 +88,13 @@ export interface ResourceState { */ readonly lifetime: object; - readonly description: Description; + readonly description: Description | undefined; } export interface ResourceBlueprintParts { readonly Constructor: ResourceConstructor; readonly metadata: M; - readonly description: Description; + readonly description: Description | undefined; } export class ResourceBlueprintImpl { @@ -101,7 +106,7 @@ export class ResourceBlueprintImpl { return new ResourceBlueprintImpl( resource as ResourceConstructor, undefined, - Desc("resource", description) + RUNTIME.Desc?.("resource", description) ); } @@ -157,12 +162,12 @@ export class ResourceBlueprintImpl { #Constructor: ResourceConstructor; #metadata: unknown; - #description: Description; + #description: Description | undefined; constructor( Constructor: ResourceConstructor, metadata: unknown, - description: Description + description: Description | undefined ) { this.#Constructor = Constructor; this.#metadata = metadata; diff --git a/packages/universal/resource/tests/package.json b/packages/universal/resource/tests/package.json index 6af01b72..3b470603 100644 --- a/packages/universal/resource/tests/package.json +++ b/packages/universal/resource/tests/package.json @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam-workspace/test-utils": "workspace:^", "@starbeam/resource": "workspace:^", diff --git a/packages/universal/resource/tests/resource-list.spec.ts b/packages/universal/resource/tests/resource-list.spec.ts index bc469fbb..211b5340 100644 --- a/packages/universal/resource/tests/resource-list.spec.ts +++ b/packages/universal/resource/tests/resource-list.spec.ts @@ -1,5 +1,5 @@ -import { DisplayStruct } from "@starbeam/debug"; -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; +import { DisplayStruct } from "@starbeam/core-utils"; import { CachedFormula, Cell } from "@starbeam/reactive"; import { Resource, diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index 51ad8d64..299fb04f 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -6,10 +6,7 @@ export { type OnCleanup, } from "./src/lifetime/api.js"; export type { Unsubscribe } from "./src/lifetime/object-lifetime.js"; -export { - type NotifyReady, - Subscriptions, -} from "./src/timeline/subscriptions.js"; +export { Subscriptions } from "./src/timeline/subscriptions.js"; export { PUBLIC_TIMELINE, type PublicTimeline, diff --git a/packages/universal/runtime/src/define.ts b/packages/universal/runtime/src/define.ts index 41f8bdec..24b34ce7 100644 --- a/packages/universal/runtime/src/define.ts +++ b/packages/universal/runtime/src/define.ts @@ -1,14 +1,14 @@ -import { callerStack } from "@starbeam/debug"; +import { debugRuntime as DEBUG_RUNTIME } from "@starbeam/debug"; import type { AutotrackingRuntime, + CallerStackFn, DebugRuntime, + DescriptionRuntime, Runtime as IRuntime, - Stack, SubscriptionRuntime, } from "@starbeam/interfaces"; import { defineRuntime } from "@starbeam/reactive"; -import { DEBUG_RUNTIME } from "./timeline/debug.js"; import { SUBSCRIPTION_RUNTIME } from "./timeline/tracker.js"; import { AUTOTRACKING_RUNTIME } from "./tracking-stack.js"; @@ -41,19 +41,27 @@ class Runtime implements IRuntime { readonly #subscriptions: SubscriptionRuntime; readonly #autotracking: AutotrackingRuntime; - readonly #debug: DebugRuntime; + readonly #debug: DebugRuntime | undefined; private constructor( subscription: SubscriptionRuntime, autotracking: AutotrackingRuntime, - debug: DebugRuntime + debug: DebugRuntime | undefined ) { this.#subscriptions = subscription; this.#autotracking = autotracking; this.#debug = debug; } - get debug(): DebugRuntime { + get Desc(): DescriptionRuntime | undefined { + return this.debug?.desc; + } + + get callerStack(): CallerStackFn | undefined { + return this.debug?.callerStack; + } + + get debug(): DebugRuntime | undefined { return this.#debug; } @@ -64,10 +72,6 @@ class Runtime implements IRuntime { get autotracking(): AutotrackingRuntime { return this.#autotracking; } - - callerStack(): Stack { - return callerStack(); - } } export const RUNTIME = Runtime.default(); diff --git a/packages/universal/runtime/src/lifetime/object-lifetime.ts b/packages/universal/runtime/src/lifetime/object-lifetime.ts index 8b183126..c7d4c530 100644 --- a/packages/universal/runtime/src/lifetime/object-lifetime.ts +++ b/packages/universal/runtime/src/lifetime/object-lifetime.ts @@ -1,4 +1,4 @@ -import { inspector } from "@starbeam/debug"; +import { inspector } from "@starbeam/core-utils"; export type Unsubscribe = () => void; diff --git a/packages/universal/runtime/src/timeline/debug.ts b/packages/universal/runtime/src/timeline/debug.ts deleted file mode 100644 index 3c04f54f..00000000 --- a/packages/universal/runtime/src/timeline/debug.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type * as interfaces from "@starbeam/interfaces"; -export class DebugRuntime implements interfaces.DebugRuntime { - untrackedReadBarrier( - _barrier: (tag: interfaces.Tag, stack: interfaces.Stack) => void | never - ): void { - /* ... */ - } -} - -export const DEBUG_RUNTIME = new DebugRuntime(); diff --git a/packages/universal/runtime/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts index 96f74df3..904456a0 100644 --- a/packages/universal/runtime/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -2,14 +2,14 @@ import type { CellTag, Diff, FormulaTag, + NotifyReady, SubscriptionTarget, Tag, } from "@starbeam/interfaces"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { diff } from "./utils.js"; - -export type NotifyReady = (internals: CellTag) => void; +import { getTargets } from "@starbeam/tags"; /** * A subscription is a weak mapping from individual cells to the subscriptions that depend on them. @@ -75,17 +75,11 @@ export class Subscriptions { * we may want to fire notifications whenever a `PolledFormula` is recomputed and produces * different dependencies. */ - register(target: Tag, ready: NotifyReady): Unsubscribe { - const subscriptionTargets = target.subscriptionTargets; - - const unsubscribes = subscriptionTargets.map((t) => - this.#register(t, ready) - ); + register(tag: Tag, ready: NotifyReady): Unsubscribe { + const unsubscribes = getTargets(tag).map((t) => this.#register(t, ready)); return () => { - for (const unsubscribe of unsubscribes) { - unsubscribe(); - } + for (const unsubscribe of unsubscribes) unsubscribe(); }; } diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index 6f52fcb1..291e8002 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -1,16 +1,17 @@ import type { CellTag, FormulaTag, + NotifyReady, SubscriptionRuntime, Tag, Tagged, Unsubscribe, } from "@starbeam/interfaces"; import { isTagged } from "@starbeam/reactive"; -import { getTag, type Timestamp } from "@starbeam/tags"; +import { getTag, getTargets, type Timestamp } from "@starbeam/tags"; import { NOW } from "@starbeam/tags"; -import { type NotifyReady, Subscriptions } from "./subscriptions.js"; +import { Subscriptions } from "./subscriptions.js"; enum Phase { read = "read", @@ -34,13 +35,10 @@ class Mutations implements SubscriptionRuntime { return this.#subscriptions.register(target, ready); } - bump(cell: CellTag): { revision: Timestamp; notify: () => void } { - return { - revision: this.#updatePhase(Phase.write), - notify: () => { - this.#subscriptions.notify(cell); - }, - }; + bump(cell: CellTag, update: (revision: Timestamp) => void): void { + const revision = this.#updatePhase(Phase.write); + update(revision); + this.#subscriptions.notify(cell); } update(formula: FormulaTag): void { @@ -63,7 +61,7 @@ export class PublicTimeline { change: (tagged: Tagged | Tag, ready: NotifyReady): Unsubscribe => { const tag = isTagged(tagged) ? getTag(tagged) : tagged; const unsubscribes = new Set(); - for (const target of tag.subscriptionTargets) { + for (const target of getTargets(tag)) { unsubscribes.add(SUBSCRIPTION_RUNTIME.subscribe(target, ready)); } diff --git a/packages/universal/runtime/tests/consume.spec.ts b/packages/universal/runtime/tests/consume.spec.ts index 0f12aa55..6d22f2f9 100644 --- a/packages/universal/runtime/tests/consume.spec.ts +++ b/packages/universal/runtime/tests/consume.spec.ts @@ -1,13 +1,10 @@ -import { Desc } from "@starbeam/debug"; -import { CachedFormula, Cell, getRuntime, Marker } from "@starbeam/reactive"; +import { CachedFormula, Cell, Marker, RUNTIME } from "@starbeam/reactive"; import { getTag } from "@starbeam/runtime"; -import { FormulaTag } from "@starbeam/tags"; +import { createFormulaTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; import { Staleness } from "./support/testing.js"; -const RUNTIME = getRuntime(); - describe("consumption", () => { test("the basics", () => { const number = Cell(1); @@ -30,7 +27,7 @@ describe("consumption", () => { // finalize the frame, which should give us back the marker's tag const tags = done(); // create a formula tag with the marker's tags - const tag = FormulaTag.create(Desc("formula"), () => tags); + const tag = createFormulaTag(RUNTIME.Desc?.("formula"), () => tags); // unset the tag's TDZ, which will allow subscriptions to the tag. Normally // this happens in the implementation of `Formula`, once the value was computed. tag.markInitialized(); diff --git a/packages/universal/runtime/tests/protocol.spec.ts b/packages/universal/runtime/tests/protocol.spec.ts index 14a55c6e..27dcc303 100644 --- a/packages/universal/runtime/tests/protocol.spec.ts +++ b/packages/universal/runtime/tests/protocol.spec.ts @@ -1,12 +1,11 @@ -import { Desc } from "@starbeam/debug"; import type { Tagged } from "@starbeam/interfaces"; -import { Cell, Static } from "@starbeam/reactive"; +import { Cell, RUNTIME, Static } from "@starbeam/reactive"; import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; import { - dependenciesInTaggedList, - FormulaTag, + createFormulaTag, + getDependencies, getTag, - lastUpdatedInTaggedList, + lastUpdated, zero, } from "@starbeam/tags"; import { describe, expect, it } from "vitest"; @@ -17,14 +16,14 @@ describe("Tagged", () => { const tom = Static("Tom Dale"); expect(String(getTag(tom).lastUpdated)).toBe(String(zero())); - expect(String(lastUpdatedInTaggedList([tom]))).toBe(String(zero())); + expect(String(lastUpdated(getTag(tom)))).toBe(String(zero())); }); it("has no dependencies", () => { const tom = Static("Tom Dale"); expect([...getTag(tom).dependencies()]).toEqual([]); - expect([...dependenciesInTaggedList([tom])]).toEqual([]); + expect(getDependencies(tom)).toEqual([]); }); }); @@ -40,8 +39,8 @@ describe("Tagged", () => { String(nullvoxTimestamp) ); expect( - String(lastUpdatedInTaggedList([tom, nullvox])), - "lastUpdatedIn([tom,nullvox])" + String(lastUpdated(tom, nullvox)), + "lastUpdated(tom,nullvox)" ).toBe(String(PUBLIC_TIMELINE.now)); expect(String(PUBLIC_TIMELINE.now)).not.toBe(String(original)); @@ -60,7 +59,7 @@ describe("Tagged", () => { expect(String(getTag(nullvox).lastUpdated)).toBe( String(nullvoxTimestamp) ); - expect(String(lastUpdatedInTaggedList([tom, nullvox]))).toBe( + expect(String(lastUpdated(tom, nullvox))).toBe( String(PUBLIC_TIMELINE.now) ); }); @@ -70,7 +69,7 @@ describe("Tagged", () => { const nullvox = Cell("nullvox"); expect([...getTag(tom).dependencies()]).toEqual([tom[TAG]]); - expect([...dependenciesInTaggedList([tom, nullvox])]).toEqual([ + expect([...getDependencies(tom, nullvox)]).toEqual([ tom[TAG], nullvox[TAG], ]); @@ -84,21 +83,19 @@ describe("Tagged", () => { nullvox.current = "@nullvoxpopuli"; expect([...getTag(tom).dependencies()]).toEqual([]); - expect([...dependenciesInTaggedList([tom, nullvox])]).toEqual([ - nullvox[TAG], - ]); + expect(getDependencies(tom, nullvox)).toEqual([nullvox[TAG]]); }); }); - describe("Composite", () => { + describe("FormulaTag", () => { it("has the maximum timestamp of its dependencies", () => { const tom = Cell("Tom"); const nullvox = Cell("nullvox"); - const formula = FormulaTag.create(Desc("formula"), () => [ - getTag(tom), - getTag(nullvox), - ]); + const formula = createFormulaTag( + RUNTIME.Desc?.("formula"), + () => new Set([getTag(tom), getTag(nullvox)]) + ); const Both: Tagged = { [TAG]: formula, diff --git a/packages/universal/runtime/tests/subscribing.spec.ts b/packages/universal/runtime/tests/subscribing.spec.ts index d3f81062..f9483243 100644 --- a/packages/universal/runtime/tests/subscribing.spec.ts +++ b/packages/universal/runtime/tests/subscribing.spec.ts @@ -1,9 +1,9 @@ import { isPresentArray } from "@starbeam/core-utils"; -import { Desc, logTag } from "@starbeam/debug"; +import { logTag } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; -import { CachedFormula, Cell } from "@starbeam/reactive"; +import { CachedFormula, Cell, RUNTIME } from "@starbeam/reactive"; import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; -import { DelegateTag, getTag } from "@starbeam/tags"; +import { createDelegateTag, getTag } from "@starbeam/tags"; import { describe, expect, test } from "vitest"; describe("Tagged", () => { @@ -79,7 +79,7 @@ describe("Tagged", () => { const delegate: ReactiveValue = { read: () => cell.current, - [TAG]: DelegateTag.create(Desc("delegate"), [getTag(cell)]), + [TAG]: createDelegateTag(RUNTIME.Desc?.("delegate"), [getTag(cell)]), }; let stale = false; @@ -104,7 +104,7 @@ describe("Tagged", () => { const delegate: ReactiveValue = { read: () => formula.current, - [TAG]: DelegateTag.create(Desc("delegate", "test delegate"), [ + [TAG]: createDelegateTag(RUNTIME.Desc?.("delegate", "test delegate"), [ getTag(formula), ]), }; @@ -129,7 +129,7 @@ describe("Tagged", () => { const delegate: ReactiveValue = { read: () => sum.read(), - [TAG]: DelegateTag.create(Desc("delegate", "test delegate"), [ + [TAG]: createDelegateTag(RUNTIME.Desc?.("delegate", "test delegate"), [ getTag(sum), ]), }; @@ -173,7 +173,7 @@ function Sum(): { sum: ReactiveValue; numbers: Cell[]>; } { - const description = Desc("formula", "Sum"); + const description = RUNTIME.Desc?.("formula", "Sum"); const numbers = Cell([] as Cell[], "number list"); const sum = CachedFormula( diff --git a/packages/universal/runtime/tests/support/testing.ts b/packages/universal/runtime/tests/support/testing.ts index 507255d1..d9a7929c 100644 --- a/packages/universal/runtime/tests/support/testing.ts +++ b/packages/universal/runtime/tests/support/testing.ts @@ -1,5 +1,4 @@ import { Overload } from "@starbeam/core-utils"; -import { callerStack, isErrorWithStack } from "@starbeam/debug"; import { expect } from "vitest"; export class Staleness { @@ -12,9 +11,6 @@ export class Staleness { | [staleness: "stale" | "fresh"] | [perform: () => T, staleness: "stale" | "fresh"] ): T | void { - // let result: T | undefined; - // let stale: "stale" | "fresh"; - const [result, stale] = Overload<[T | undefined, "stale" | "fresh"]>() .of(args) .resolve({ @@ -22,19 +18,7 @@ export class Staleness { [2]: (perform, staleness) => [perform(), staleness], }); - const stack = callerStack(); - try { - expect(this.#stale ? "stale" : "fresh").toBe(stale); - } catch (e) { - if (isErrorWithStack(e)) { - const [errorHeader] = splitStack(e.stack); - const [, callerStack] = splitStack(stack.stack); - - e.stack = `${errorHeader}\n${callerStack}`; - } - - throw e; - } + expect(this.#stale ? "stale" : "fresh").toBe(stale); this.#stale = false; return result; } @@ -43,17 +27,3 @@ export class Staleness { this.#stale = true; } } - -function splitStack(stack: string): [string, string] { - // find the first line that starts with "at" (with possible whitespace) - const lines = stack.split("\n"); - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - if (line?.trimStart().startsWith("at ")) { - return [lines.slice(0, i).join("\n"), lines.slice(i).join("\n")]; - } - } - - return [stack, ""]; -} diff --git a/packages/universal/service/src/service.ts b/packages/universal/service/src/service.ts index a48b7e76..716fa56d 100644 --- a/packages/universal/service/src/service.ts +++ b/packages/universal/service/src/service.ts @@ -1,5 +1,5 @@ -import { Desc } from "@starbeam/debug"; import type { Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import type { IntoResourceBlueprint } from "@starbeam/resource"; import { Resource, type ResourceBlueprint, use } from "@starbeam/resource"; import { CONTEXT } from "@starbeam/runtime"; @@ -14,14 +14,14 @@ export function Service( return CONTEXT.create(blueprint, () => { return use(blueprint); }); - }, Desc("blueprint:service", description).detail("service")); + }, RUNTIME.Desc?.("service", description)); } export function service( resource: Blueprint, description?: string | Description ): Resource { - return use(Service(resource, Desc("blueprint:resource", description)), { + return use(Service(resource, RUNTIME.Desc?.("service", description)), { lifetime: CONTEXT.app, }); } diff --git a/packages/universal/service/tests/package.json b/packages/universal/service/tests/package.json index 3b71d262..d1f58dc8 100644 --- a/packages/universal/service/tests/package.json +++ b/packages/universal/service/tests/package.json @@ -11,7 +11,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", diff --git a/packages/universal/tags/index.ts b/packages/universal/tags/index.ts index 3f31b58c..b425d4b7 100644 --- a/packages/universal/tags/index.ts +++ b/packages/universal/tags/index.ts @@ -1,19 +1,16 @@ export { - CellTag, - DelegateTag, - FormulaTag, - StaticTag, - /** @deprecated */ - Tag, - Tag as TagUtils, + createCellTag, + createDelegateTag, + createFormulaTag, + createStaticTag, + getTargets, } from "./src/tag.js"; export { - dependenciesInTaggedList, - describeTagged, + getDependencies, + getDescription, getTag, getTags, - lastUpdatedInTaggedList, - taggedDescription, + lastUpdated, } from "./src/tagged.js"; export { debug as debugTimestamp, @@ -24,3 +21,9 @@ export { Timestamp, zero, } from "./src/timestamp.js"; +export type { + CellTag, + DelegateTag, + FormulaTag, + StaticTag, +} from "@starbeam/interfaces"; diff --git a/packages/universal/tags/package.json b/packages/universal/tags/package.json index 04c451f9..71abfa37 100644 --- a/packages/universal/tags/package.json +++ b/packages/universal/tags/package.json @@ -17,7 +17,7 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/debug": "workspace:^", + "@starbeam/core-utils": "workspace:^", "@starbeam/interfaces": "workspace:^", "@starbeam/shared": "workspace:^" }, diff --git a/packages/universal/tags/src/tag.ts b/packages/universal/tags/src/tag.ts index fc6ddd46..005cb5cb 100644 --- a/packages/universal/tags/src/tag.ts +++ b/packages/universal/tags/src/tag.ts @@ -1,252 +1,107 @@ -import { DisplayStruct } from "@starbeam/debug"; -import type { Description, UpdateOptions } from "@starbeam/interfaces"; -import type * as interfaces from "@starbeam/interfaces"; - -import { type Timestamp, zero } from "./timestamp.js"; +import { dataGetter, def } from "@starbeam/core-utils"; +import type { + CellTag, + DelegateTag, + Description, + FormulaTag, + StaticTag, + SubscriptionTarget, + Tag, + TagSet, + UpdateOptions, +} from "@starbeam/interfaces"; + +import { lastUpdated } from "./tagged.js"; import { NOW } from "./timestamp.js"; -const INSPECT = Symbol.for("nodejs.util.inspect.custom"); - -export abstract class Tag - implements interfaces.AbstractTag, interfaces.TagMethods -{ - static lastUpdatedIn( - this: void, - tags: interfaces.List - ): Timestamp { - let lastUpdatedTimestamp = zero(); - - for (const child of Tag.dependenciesInList(tags)) { - if (child.lastUpdated.gt(lastUpdatedTimestamp)) { - lastUpdatedTimestamp = child.lastUpdated; - } +export function createCellTag( + description: Description | undefined, + lastUpdated = NOW.bump() +): CellTag { + let frozen = false; + + const tag: CellTag = def( + { + type: "cell", + description, + isFrozen: () => frozen, + freeze: () => (frozen = true), + dependencies: () => (frozen ? [] : [tag]), + update: ({ runtime }: UpdateOptions) => { + if (frozen) throw TypeError("Cannot update frozen object"); + runtime.subscriptions.bump(tag, (ts) => (lastUpdated = ts)); + }, + }, + { + lastUpdated: dataGetter(() => lastUpdated), } + ); - return lastUpdatedTimestamp; - } - - static *dependenciesInList( - this: void, - children: interfaces.List - ): Iterable { - for (const child of children) { - yield* child.dependencies(); - } - } - - abstract readonly type: interfaces.TagType; - abstract readonly initialized: boolean; - abstract readonly subscriptionTargets: readonly interfaces.SubscriptionTarget[]; - - readonly #description: Description; - constructor(description: Description) { - this.#description = description; - } - - get id(): interfaces.ReactiveId { - return this.#description.id; - } - - match(matcher: interfaces.Matcher): T { - const fn = matcher[this.type]; - if (typeof fn === "function") { - return fn(this as never); - } - - return (matcher as interfaces.DefaultMatcher).default( - this as interfaces.Tag - ); - } - - abstract readonly lastUpdated: Timestamp; - - abstract dependencies(): readonly interfaces.CellTag[]; - - get description(): Description { - return this.#description; - } + return tag; } -export class CellTag extends Tag implements interfaces.CellTag { - static create(description: Description, lastUpdated = NOW.bump()): CellTag { - return new CellTag(description, lastUpdated); - } - - readonly type = "cell"; - readonly initialized = true; - - #frozen = false; - #lastUpdated: Timestamp; - - private constructor(description: Description, lastUpdated: Timestamp) { - super(description); - this.#lastUpdated = lastUpdated; - } - - [INSPECT]() { - return DisplayStruct("Cell", { - id: this.description.id, - lastUpdated: this.lastUpdated, - }); - } - - isFrozen() { - return this.#frozen; - } - - freeze() { - this.#frozen = true; - } - - get lastUpdated(): Timestamp { - return this.#lastUpdated; - } - - set lastUpdated(timestamp: Timestamp) { - this.#lastUpdated = timestamp; - } - - get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { - return [this as interfaces.SubscriptionTarget]; - } - - override dependencies(): interfaces.CellTag[] { - return this.#frozen ? [] : [this]; - } - - update({ runtime }: UpdateOptions): void { - if (this.#frozen) { - throw TypeError("Cannot update frozen object"); - } - - const { notify, revision } = runtime.subscriptions.bump(this); - this.#lastUpdated = revision; - notify(); - } +export function createStaticTag( + description?: Description | undefined +): StaticTag { + return { + type: "static", + description, + lastUpdated: NOW.now, + dependencies: () => [], + }; } -export class StaticTag extends Tag implements interfaces.StaticTag { - static create(description: Description): StaticTag { - return new StaticTag(description); - } - - readonly type = "static"; - readonly initialized = true; - - override readonly lastUpdated = NOW.now; - - get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { - return []; - } - - override dependencies(): readonly interfaces.CellTag[] { - return []; - } +export function createFormulaTag( + description: Description | undefined, + children: () => TagSet +): FormulaTag { + let initialized = false; + + const dependencies = () => + [...children()].flatMap((child) => child.dependencies()); + + return def( + { + type: "formula", + description, + markInitialized: () => (initialized = true), + children, + dependencies, + }, + { + initialized: dataGetter(() => initialized), + lastUpdated: dataGetter(() => lastUpdated(...dependencies())), + } + ); } -export class FormulaTag extends Tag implements interfaces.FormulaTag { - static create( - description: Description, - children: () => interfaces.List - ): FormulaTag { - return new FormulaTag(description, children, false); - } - - readonly type = "formula"; - readonly #children: () => interfaces.List; - #initialized: boolean; - - private constructor( - description: Description, - children: () => interfaces.List, - initialized: boolean - ) { - super(description); - this.#children = children; - this.#initialized = initialized; - } - - [INSPECT]() { - return DisplayStruct("Formula", { - id: this.description.id, - initialized: this.#initialized, - children: [...this.#children()], - }); - } - - get initialized(): boolean { - return this.#initialized; - } - - markInitialized(): void { - this.#initialized = true; - } - - children(): readonly interfaces.Tag[] { - return [...this.#children()]; - } - - override get lastUpdated(): interfaces.Timestamp { - let lastUpdatedTimestamp = zero(); - - for (const child of this.dependencies()) { - if (child.lastUpdated.gt(lastUpdatedTimestamp)) { - lastUpdatedTimestamp = child.lastUpdated; - } +export function createDelegateTag( + description: Description | undefined, + targets: readonly Tag[] +): DelegateTag { + return def( + { + type: "delegate", + description, + targets, + dependencies: () => targets.flatMap((target) => target.dependencies()), + }, + { + lastUpdated: dataGetter(() => lastUpdated(...targets)), + subscriptionTargets: dataGetter(() => targets.flatMap(getTargets)), } - - return lastUpdatedTimestamp; - } - - override dependencies(): interfaces.CellTag[] { - return this.children().flatMap((child) => child.dependencies()); - } - - get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { - return [this]; - } + ); } -export class DelegateTag extends Tag implements interfaces.DelegateTag { - static create( - description: Description, - targets: readonly interfaces.Tag[] - ): DelegateTag { - return new DelegateTag(description, targets); - } - - readonly type = "delegate"; - readonly #targets: readonly interfaces.Tag[]; - readonly #subscriptionTargets: readonly interfaces.SubscriptionTarget[]; - - private constructor( - description: Description, - targets: readonly interfaces.Tag[] - ) { - super(description); - this.#targets = targets; - this.#subscriptionTargets = targets.flatMap( - (target) => target.subscriptionTargets - ); - } - - get initialized(): boolean { - return this.#targets.every((target) => target.initialized); - } - - get targets(): readonly interfaces.Tag[] { - return this.#targets; - } - - get subscriptionTargets(): readonly interfaces.SubscriptionTarget[] { - return this.#subscriptionTargets; - } - - override dependencies(): readonly interfaces.CellTag[] { - return this.#targets.flatMap((target) => target.dependencies()); - } - - override get lastUpdated(): Timestamp { - return Tag.lastUpdatedIn(this.subscriptionTargets); +export function getTargets(tag: Tag): SubscriptionTarget[] { + switch (tag.type) { + case "static": + return []; + case "cell": + return tag.isFrozen() ? [] : [tag]; + case "formula": + return [tag]; + case "delegate": + return tag.targets.flatMap(getTargets); } } diff --git a/packages/universal/tags/src/tagged.ts b/packages/universal/tags/src/tagged.ts index fe2d1934..5d537203 100644 --- a/packages/universal/tags/src/tagged.ts +++ b/packages/universal/tags/src/tagged.ts @@ -1,7 +1,6 @@ import type { CellTag, Description, - DescriptionDescribeOptions, Tag, Tagged, Timestamp, @@ -10,41 +9,32 @@ import { TAG } from "@starbeam/shared"; import { zero } from "./timestamp.js"; -export function getTag(tagged: Tagged): T { - return tagged[TAG]; -} +type HasTag = T | Tagged; -export function getTags( - tagged: T -): { [P in keyof T]: T[P] extends Tagged ? U : never } { - return tagged.map(getTag) as any; +export function getTag(tagged: HasTag): T { + return TAG in tagged ? tagged[TAG] : tagged; } -export function describeTagged( - tagged: Tagged, - options?: DescriptionDescribeOptions -): string { - return getTag(tagged).description.describe(options); +export function getTags[]>( + tagged: T +): { [P in keyof T]: T[P] extends HasTag ? U : never } { + return tagged.map(getTag) as never; } -export function taggedDescription(tagged: Tagged): Description { +export function getDescription(tagged: HasTag): Description | undefined { return getTag(tagged).description; } -export function* dependenciesInTaggedList( - taggedList: readonly Tagged[] -): Iterable { - for (const child of taggedList.map(getTag)) { - yield* child.dependencies(); - } +export function getDependencies( + ...taggedList: readonly HasTag[] +): readonly CellTag[] { + return taggedList.flatMap((tagged) => getTag(tagged).dependencies()); } -export function lastUpdatedInTaggedList( - taggedList: readonly Tagged[] -): Timestamp { +export function lastUpdated(...taggedList: readonly HasTag[]): Timestamp { let lastUpdatedTimestamp = zero(); - for (const child of dependenciesInTaggedList(taggedList)) { + for (const child of getDependencies(...taggedList)) { if (child.lastUpdated.gt(lastUpdatedTimestamp)) { lastUpdatedTimestamp = child.lastUpdated; } diff --git a/packages/universal/tags/src/timestamp.ts b/packages/universal/tags/src/timestamp.ts index 85eb53f8..a50c5fa8 100644 --- a/packages/universal/tags/src/timestamp.ts +++ b/packages/universal/tags/src/timestamp.ts @@ -1,4 +1,4 @@ -import { DisplayStruct } from "@starbeam/debug"; +import { DisplayStruct } from "@starbeam/core-utils"; import type * as interfaces from "@starbeam/interfaces"; import { bump as peerBump, now as peerNow } from "@starbeam/shared"; diff --git a/packages/universal/test-utils/tsconfig.json b/packages/universal/test-utils/tsconfig.json deleted file mode 100644 index 4790a1ab..00000000 --- a/packages/universal/test-utils/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../../.config/tsconfig/tsconfig.shared.json", - "compilerOptions": { - "composite": true, - "declaration": true, - "declarationDir": "../../../dist/types", - "declarationMap": true, - "outDir": "../../../dist/packages", - "types": ["../../env"] - }, - "exclude": ["dist/**/*"] -} diff --git a/packages/universal/universal/CONCEPTS.md b/packages/universal/universal/CONCEPTS.md index bdc493e1..a26dd49d 100644 --- a/packages/universal/universal/CONCEPTS.md +++ b/packages/universal/universal/CONCEPTS.md @@ -283,7 +283,7 @@ const UserSession = Resource(({ on }) => { As a Class ```ts -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; class UserSession { @reactive #user: User | null = null; diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 2800f60a..3a848b2a 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -1,17 +1,5 @@ export { DEBUG_RENDERER } from "./src/debug-renderer.js"; -export { - Custom, - CustomBlueprint, - CustomBuilder, -} from "./src/reactive-core/custom.js"; export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; -export type { - Blueprint, - IntoReactive, - ReactiveBlueprint, - ReactiveFactory, -} from "./src/reactive-core/reactive.js"; -export { Reactive } from "./src/reactive-core/reactive.js"; export { type Variant, type VariantEntry, diff --git a/packages/universal/universal/src/debug-renderer.ts b/packages/universal/universal/src/debug-renderer.ts index fa221ddc..cb8e21c7 100644 --- a/packages/universal/universal/src/debug-renderer.ts +++ b/packages/universal/universal/src/debug-renderer.ts @@ -1,6 +1,5 @@ -import { type Description, descriptionFrom } from "@starbeam/debug"; -import type { Unsubscribe } from "@starbeam/interfaces"; -import { Formula } from "@starbeam/reactive"; +import type { Description, Unsubscribe } from "@starbeam/interfaces"; +import { Formula, RUNTIME } from "@starbeam/reactive"; import { PUBLIC_TIMELINE } from "@starbeam/runtime"; export const DEBUG_RENDERER = { @@ -16,11 +15,7 @@ export const DEBUG_RENDERER = { ): Unsubscribe { const formula = Formula( render, - descriptionFrom({ - type: "renderer", - api: "DEBUG_RENDERER", - fromUser: description, - }) + RUNTIME.Desc?.("formula", description ?? "DEBUG_RENDERER") ); debug(formula.read()); diff --git a/packages/universal/universal/src/reactive-core/custom.ts b/packages/universal/universal/src/reactive-core/custom.ts deleted file mode 100644 index 0e2bfcb8..00000000 --- a/packages/universal/universal/src/reactive-core/custom.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { Reactive } from "./reactive.js"; - -export function Custom( - this: void, - create: (builder: CustomBuilder) => A -): CustomBlueprint { - return { - setup: () => { - const builder = new CustomBuilder(); - return create(builder); - }, - }; -} - -Custom.create = Custom; - -Custom.class = ( - create: new (...args: A) => R -): ((...args: A) => CustomBlueprint) => { - return (...args: A) => CustomBlueprint.fn(() => new create(...args)); -}; - -Custom.fn = ( - create: (...args: A) => R -): ((...args: A) => CustomBlueprint) => { - return (...args: A) => CustomBlueprint.fn(() => create(...args)); -}; - -export class CustomBuilder {} - -export class CustomBlueprint { - static fn( - this: void, - create: (builder: CustomBuilder) => T - ): CustomBlueprint { - return new CustomBlueprint(create); - } - - readonly setup: () => T; - - private constructor(setup: (builder: CustomBuilder) => T) { - const builder = new CustomBuilder(); - this.setup = () => setup(builder); - } -} - -export type CustomInstance = Reactive | T; -export type CustomInstanceValue CustomInstance> = - ReturnType extends Reactive - ? Reactive - : Reactive>; diff --git a/packages/universal/universal/src/reactive-core/higher-level/freshness.ts b/packages/universal/universal/src/reactive-core/higher-level/freshness.ts index 8487bd77..7d0ccf86 100644 --- a/packages/universal/universal/src/reactive-core/higher-level/freshness.ts +++ b/packages/universal/universal/src/reactive-core/higher-level/freshness.ts @@ -1,5 +1,5 @@ -import { type Description, descriptionFrom } from "@starbeam/debug"; -import { Cell } from "@starbeam/reactive"; +import type { Description } from "@starbeam/interfaces"; +import { Cell, RUNTIME } from "@starbeam/reactive"; const INITIAL_COUNT = 0; const INCREMENT_COUNT = 1; @@ -8,7 +8,7 @@ export class ReactiveFreshness { #lastChecked: number | undefined; #cell: Cell; - constructor(description: Description) { + constructor(description: Description | undefined) { this.#cell = Cell(INITIAL_COUNT, { description }); } @@ -36,13 +36,7 @@ export class ReactiveFreshness { export function Freshness( description?: string | Description ): ReactiveFreshness { - return new ReactiveFreshness( - descriptionFrom({ - type: "cell", - api: { package: "@starbeam/universal", name: "Freshness" }, - fromUser: description, - }) - ); + return new ReactiveFreshness(RUNTIME.Desc?.("cell", description)); } export type Freshness = ReactiveFreshness; diff --git a/packages/universal/universal/src/reactive-core/reactive.ts b/packages/universal/universal/src/reactive-core/reactive.ts deleted file mode 100644 index ed372d0b..00000000 --- a/packages/universal/universal/src/reactive-core/reactive.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Desc, type Description } from "@starbeam/debug"; -import type { ReactiveValue, Tag } from "@starbeam/interfaces"; -import type * as interfaces from "@starbeam/interfaces"; -import type { ResourceBlueprint } from "@starbeam/resource"; -import { isObject } from "@starbeam/verify"; - -export type ReactiveFactory = - | (() => T) - | (new () => T) - | ReactiveBlueprint; - -export function Reactive( - this: void, - constructor: ReactiveFactory, - description?: string | Description -): ReactiveBlueprint { - const desc = Desc("blueprint:reactive", description); - return new ReactiveBlueprint(constructor, desc); -} - -export type IntoReactive = interfaces.Reactive | T; - -export type TypedReactive = ReactiveValue; - -export type Reactive = interfaces.Reactive; - -export class ReactiveBlueprint { - static is(value: T | ReactiveBlueprint): value is ReactiveBlueprint { - return isObject(value) && value instanceof ReactiveBlueprint; - } - - readonly #create: ReactiveFactory; - readonly #description: Description; - - constructor(create: ReactiveFactory, description: Description) { - this.#create = create; - this.#description = description; - } - - create(_owner?: object): T { - const value = construct(this.#create) as T | ReactiveBlueprint; - - if (ReactiveBlueprint.is(value)) { - return value.create(); - } else { - return value; - } - } - - isResource(): this is ResourceBlueprint { - return false; - } -} - -export function create(blueprint: ReactiveBlueprint): T { - return blueprint.create(); -} - -function construct(constructor: ReactiveFactory): T | Reactive { - try { - return (constructor as () => T | Reactive)(); - } catch { - return new (constructor as new () => T)(); - } -} - -export type Blueprint = ResourceBlueprint; diff --git a/packages/universal/universal/src/reactive-core/variants.ts b/packages/universal/universal/src/reactive-core/variants.ts index 25f42c7a..67921901 100644 --- a/packages/universal/universal/src/reactive-core/variants.ts +++ b/packages/universal/universal/src/reactive-core/variants.ts @@ -1,19 +1,23 @@ -import type { Stack } from "@starbeam/debug"; -import { - callerStack, - type Description, - descriptionFrom, - DisplayStruct, -} from "@starbeam/debug"; -import { Cell, getRuntime, Marker } from "@starbeam/reactive"; +import { DisplayStruct } from "@starbeam/core-utils"; +import type { + CallStack, + DelegateTag, + Description, + FormulaTag, +} from "@starbeam/interfaces"; +import { Cell, Marker, RUNTIME } from "@starbeam/reactive"; import type { Tagged } from "@starbeam/runtime"; import { TAG } from "@starbeam/runtime"; import { UNINITIALIZED } from "@starbeam/shared"; -import { FormulaTag, getTag, getTags } from "@starbeam/tags"; -import { DelegateTag } from "@starbeam/tags"; +import { + createDelegateTag, + createFormulaTag, + getTag, + getTags, +} from "@starbeam/tags"; export class VariantGroups { - static empty(description: Description): VariantGroups { + static empty(description: Description | undefined): VariantGroups { return new VariantGroups(description); } @@ -22,9 +26,9 @@ export class VariantGroups { // an index of all variant groups, indexed by each of their members readonly #groupsByType = new Map>(); - readonly #description: Description; + readonly #description: Description | undefined; - constructor(description: Description) { + constructor(description: Description | undefined) { this.#description = description; } @@ -44,7 +48,7 @@ export class VariantGroups { return group; } - transition(from: string, to: string, caller: Stack): void { + transition(from: string, to: string, caller: CallStack | undefined): void { const fromGroups = this.#groupsByType.get(from); const toGroups = this.#groupsByType.get(to); @@ -64,7 +68,7 @@ export class VariantGroups { #create(types: string[], joined: string): VariantGroup { const group = VariantGroup.group( types, - this.#description.detail("is", [types.join(" | ")]) + this.#description?.detail("formula", "is", [types.join(" | ")]) ); for (const type of types) { @@ -84,7 +88,10 @@ export class VariantGroups { } export class VariantGroup { - static group(types: string[], description: Description): VariantGroup { + static group( + types: string[], + description: Description | undefined + ): VariantGroup { return new VariantGroup(Marker({ description }), new Set(types)); } @@ -106,7 +113,7 @@ export class VariantGroup { // Transition to or from another variant. If the variant is not present in this group, then this // group is invalidated. - transition(type: string, caller: Stack): void { + transition(type: string, caller: CallStack | undefined): void { if (this.#types.has(type)) { return; } @@ -120,18 +127,18 @@ export class Variant implements Tagged { type: string, typeMarker: Marker, value: T, - description: Description + description: Description | undefined ): Variant { const val = Cell(value as T | UNINITIALIZED, { - description: description.implementation(type, { - reason: `${type} cell`, - }), + description: description?.implementation("cell", type, `${type} cell`), }); const localTypeMarker = Marker({ - description: description.implementation("selected:local", { - reason: "selected", - }), + description: description?.implementation( + "cell", + "selected:local", + "selected" + ), }); return new Variant( @@ -140,10 +147,8 @@ export class Variant implements Tagged { localTypeMarker, val, { value }, - DelegateTag.create( - description.implementation("selected", { - reason: `selected`, - }), + createDelegateTag( + description?.implementation("formula", "selected", "selected"), getTags([val, localTypeMarker]) ) ); @@ -152,14 +157,16 @@ export class Variant implements Tagged { static deselected( type: string, typeMarker: Marker, - description: Description + description: Description | undefined ): Variant { const val = Cell(UNINITIALIZED as T | UNINITIALIZED); const localTypeMarker = Marker({ - description: description.implementation("selected:local", { - reason: "selected", - }), + description: description?.implementation( + "cell", + "selected:local", + "selected" + ), }); return new Variant( @@ -169,8 +176,8 @@ export class Variant implements Tagged { val, { value: UNINITIALIZED }, - DelegateTag.create( - description.implementation("selected", { reason: "selected" }), + createDelegateTag( + description?.implementation("formula", "selected", "selected"), getTags([val, localTypeMarker]) ) ) as Variant; @@ -188,15 +195,25 @@ export class Variant implements Tagged { }; } - static set(variant: Variant, value: T, caller = callerStack()): void { + static set( + variant: Variant, + value: T, + caller = RUNTIME.callerStack?.() + ): void { variant.#value.set(value, caller); } - static select(variant: Variant, caller = callerStack()): void { + static select( + variant: Variant, + caller = RUNTIME.callerStack?.() + ): void { variant.#localTypeMarker.mark(caller); } - static deselect(variant: Variant, caller = callerStack()): void { + static deselect( + variant: Variant, + caller = RUNTIME.callerStack?.() + ): void { variant.#localTypeMarker.mark(caller); } @@ -327,16 +344,16 @@ export interface Variants extends Tagged { class VariantsImpl implements Tagged { static create( value: InternalVariant, - description: Description + description: Description | undefined ): VariantsImpl { const variants: Record> = {}; - const typeMarker = Marker({ description: description.key("type") }); + const typeMarker = Marker({ description: description?.key("type") }); const current = Variant.selected( value.type, typeMarker, value.value, - description.key(value.type) + description?.key(value.type) ); variants[value.type] = current; @@ -346,14 +363,14 @@ class VariantsImpl implements Tagged { readonly #variants: Record>; readonly #typeMarker: Marker; readonly #groups: VariantGroups; - readonly #description: Description; + readonly #description: Description | undefined; readonly [TAG]: FormulaTag; #current: Variant; private constructor( variants: Record>, type: Marker, - description: Description, + description: Description | undefined, current: Variant ) { this.#variants = variants; @@ -361,13 +378,12 @@ class VariantsImpl implements Tagged { this.#groups = VariantGroups.empty(description); this.#description = description; this.#current = current; - this[TAG] = FormulaTag.create(description, () => [getTag(this.#current)]); + this[TAG] = createFormulaTag( + description, + () => new Set([getTag(this.#current)]) + ); } - // get [TAG](): FormulaTag { - // return CompositeInternals([this.#current], this.#description); - // } - get current(): Variant { return this.#current; } @@ -415,7 +431,7 @@ class VariantsImpl implements Tagged { } choose(type: string, value?: unknown): void { - const caller = callerStack(); + const caller = RUNTIME.callerStack?.(); const current = this.#current; const from = Variant.type(current); @@ -438,7 +454,7 @@ class VariantsImpl implements Tagged { } this.#typeMarker.mark(caller); - getRuntime().subscriptions.update(this[TAG]); + RUNTIME.subscriptions.update(this[TAG]); } #get(type: string): Variant { @@ -459,7 +475,7 @@ class VariantsImpl implements Tagged { return (this.#variants[type] = Variant.deselected( type, this.#typeMarker, - this.#description.key(type) + this.#description?.key(type) )); } else { const [, value] = create; @@ -467,7 +483,7 @@ class VariantsImpl implements Tagged { type, this.#typeMarker, value, - this.#description.key(type) + this.#description?.key(type) )); } } @@ -484,14 +500,7 @@ for (const name of Object.keys( export function Variants( description?: string | Description ): VariantConstructors { - const desc = descriptionFrom({ - type: "variants", - api: { - package: "@starbeam/universal", - name: "Variants", - }, - fromUser: description, - }); + const desc = RUNTIME.Desc?.("collection", description, "Variants"); const target: Record VariantsImpl> = {}; return new Proxy(target, { get(getTarget, name) { diff --git a/packages/universal/universal/tests/custom.spec.ts b/packages/universal/universal/tests/custom.spec.ts deleted file mode 100644 index 417c897a..00000000 --- a/packages/universal/universal/tests/custom.spec.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { intoReactive, read } from "@starbeam/reactive"; -import type { CustomBlueprint, Reactive } from "@starbeam/universal"; -import { type IntoReactive } from "@starbeam/universal"; -import { Cell, Custom, Formula } from "@starbeam/universal"; -import { describe, expect, test } from "vitest"; - -describe("Custom reactive objects", () => { - test("a custom reactive object containing a cell", () => { - const Counter = Custom(() => { - const count = Cell(0); - - return { - get count() { - return count.current; - }, - - increment() { - count.update((value) => value + 1); - }, - }; - }); - - const counter = Counter.setup(); - expect(counter.count).toBe(0); - counter.increment(); - expect(counter.count).toBe(1); - - // multiple instance of Counter have their own state - const counter2 = Counter.setup(); - expect(counter2.count).toBe(0); - counter2.increment(); - expect(counter2.count).toBe(1); - expect(counter.count).toBe(1); - - counter.increment(); - expect(counter.count).toBe(2); - }); - - test("a custom reactive object parameters and returning a formula", () => { - function FormattedDate( - date: IntoReactive, - locale?: IntoReactive - ): CustomBlueprint> { - return Custom(() => { - const formatter = Formula( - () => - new Intl.DateTimeFormat(read(locale), { - year: "numeric", - month: "long", - day: "numeric", - }) - ); - - return Formula(() => { - return formatter().format(read(date)); - }); - }); - } - - // create a cell containing a date for January 1, 2020 - const date = Cell(new Date(2020, 0, 1)); - - const withoutLocale = FormattedDate(date).setup(); - expect(withoutLocale.current).toBe("January 1, 2020"); - - const withLocale = FormattedDate(date, Cell("en-GB")).setup(); - expect(withLocale.current).toBe("1 January 2020"); - - date.update((value) => new Date(value.setFullYear(2021))); - expect(withoutLocale.current).toBe("January 1, 2021"); - expect(withLocale.current).toBe("1 January 2021"); - }); - - test("a custom reactive object taking generic parameters", () => { - function Person( - name: IntoReactive - ): CustomBlueprint<{ name: Reactive; age: number }> { - return Custom(() => { - const age = Cell(0); - return { - name: intoReactive(name), - - get age() { - return age.current; - }, - - set age(value: number) { - age.set(value); - }, - }; - }); - } - - const person = Person("John").setup(); - - expect(person.name.current).toBe("John"); - expect(person.age).toBe(0); - - person.age = 10; - expect(person.age).toBe(10); - }); - - test("a custom reactive object returning an instance of a class that takes generic parameters", () => { - const Person = Custom.fn( - (name: IntoReactive) => new GenericImpl(name) - ); - - const person = Person("John").setup(); - - expect(person.name).toBe("John"); - expect(person.age).toBe(0); - - person.age = 10; - expect(person.age).toBe(10); - }); - - test("a custom reactive object using Custom.class with a generic class", () => { - const Person = Custom.class(GenericImpl); - - const person = Person("John").setup(); - - expect(person.name).toBe("John"); - expect(person.age).toBe(0); - - person.age = 10; - expect(person.age).toBe(10); - }); - - test("a custom reactive object returning an instance of a class", () => { - const Counter = Custom.fn(() => new CounterImpl()); - - const counter = Counter().setup(); - expect(counter.count).toBe(0); - - counter.increment(); - expect(counter.count).toBe(1); - - // multiple instance of Counter have their own state - const counter2 = Counter().setup(); - expect(counter2.count).toBe(0); - counter2.increment(); - expect(counter2.count).toBe(1); - expect(counter.count).toBe(1); - - counter.increment(); - expect(counter.count).toBe(2); - expect(counter2.count).toBe(1); - }); -}); - -class GenericImpl { - readonly #name: Reactive; - readonly #age = Cell(0); - - constructor(name: IntoReactive) { - this.#name = intoReactive(name); - } - - get name(): S { - return this.#name.current; - } - - get age(): number { - return this.#age.current; - } - - set age(value: number) { - this.#age.set(value); - } -} - -class CounterImpl { - #cell = Cell(0); - - get count(): number { - return this.#cell.current; - } - - increment(): void { - this.#cell.update((value) => value + 1); - } -} diff --git a/packages/universal/universal/tests/formula.spec.ts b/packages/universal/universal/tests/formula.spec.ts index 4baa5364..cc696f53 100644 --- a/packages/universal/universal/tests/formula.spec.ts +++ b/packages/universal/universal/tests/formula.spec.ts @@ -1,4 +1,4 @@ -import { cached, reactive } from "@starbeam/js"; +import { cached, reactive } from "@starbeam/collections"; import { Cell, Formula } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/universal/tests/higher-level/formula-list.spec.ts b/packages/universal/universal/tests/higher-level/formula-list.spec.ts index 3a8638d7..d5bcc805 100644 --- a/packages/universal/universal/tests/higher-level/formula-list.spec.ts +++ b/packages/universal/universal/tests/higher-level/formula-list.spec.ts @@ -1,4 +1,4 @@ -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; import { FormulaList } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/universal/tests/package.json b/packages/universal/universal/tests/package.json index 663b1d77..88144607 100644 --- a/packages/universal/universal/tests/package.json +++ b/packages/universal/universal/tests/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@starbeam/debug": "workspace:^", - "@starbeam/js": "workspace:^", + "@starbeam/collections": "workspace:^", "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" diff --git a/packages/universal/universal/tests/polled-formula.spec.ts b/packages/universal/universal/tests/polled-formula.spec.ts index 1c268111..ad0101c3 100644 --- a/packages/universal/universal/tests/polled-formula.spec.ts +++ b/packages/universal/universal/tests/polled-formula.spec.ts @@ -1,4 +1,4 @@ -import { cached, reactive } from "@starbeam/js"; +import { cached, reactive } from "@starbeam/collections"; import { Cell, PolledFormula } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 1668c694..10102039 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,5 +1,5 @@ +import { RUNTIME } from "@starbeam/reactive"; import { PUBLIC_TIMELINE, type Tagged } from "@starbeam/runtime"; -import { describeTagged } from "@starbeam/tags"; import { Formula, Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; @@ -215,8 +215,11 @@ function Stability(reactive: Tagged): { PUBLIC_TIMELINE.on.change(reactive, (internals) => { if (debug) { - console.group(describeTagged(reactive), "invalidated by"); - console.log(internals.description.describe()); + console.group( + RUNTIME.debug?.describeTagged(reactive) ?? "{unknown reactive value}", + "invalidated by" + ); + console.log(internals.description); console.groupEnd(); } changed = true; diff --git a/packages/x/devtool/src/log/cell.tsx b/packages/x/devtool/src/log/cell.tsx index 85af9288..d028abd5 100644 --- a/packages/x/devtool/src/log/cell.tsx +++ b/packages/x/devtool/src/log/cell.tsx @@ -5,7 +5,7 @@ import type { CellConsumeOperation, CellUpdateOperation, } from "@starbeam/debug"; -import type { Timestamp } from "@starbeam/interfaces"; +import type { Timestamp } from "@starbeam/interfaces/index.js"; import type { JSX } from "preact"; import type { DevtoolsOptions } from "./shared.js"; diff --git a/packages/x/devtool/src/log/describe.tsx b/packages/x/devtool/src/log/describe.tsx index 81fe3dfb..fbd9fc58 100644 --- a/packages/x/devtool/src/log/describe.tsx +++ b/packages/x/devtool/src/log/describe.tsx @@ -6,7 +6,7 @@ import type { DescriptionParts, DetailsPart, StackFrameDisplayOptions, -} from "@starbeam/interfaces"; +} from "@starbeam/interfaces/index.js"; import type { ComponentChildren, JSX } from "preact"; import type { DevtoolsOptions } from "./shared.js"; diff --git a/packages/x/devtool/src/log/frame.tsx b/packages/x/devtool/src/log/frame.tsx index 986e10a4..755ee276 100644 --- a/packages/x/devtool/src/log/frame.tsx +++ b/packages/x/devtool/src/log/frame.tsx @@ -1,7 +1,7 @@ /** @jsxRuntime automatic @jsxImportSource preact */ import type { FrameConsumeOperation } from "@starbeam/debug"; -import type { MutableInternals, Timestamp } from "@starbeam/interfaces"; +import type { MutableInternals, Timestamp } from "@starbeam/interfaces/index.js"; import { ReactiveInternals } from "@starbeam/runtime"; import type { JSX } from "preact"; diff --git a/packages/x/devtool/src/log/log.tsx b/packages/x/devtool/src/log/log.tsx index 03926f2b..bfb210b5 100644 --- a/packages/x/devtool/src/log/log.tsx +++ b/packages/x/devtool/src/log/log.tsx @@ -2,7 +2,7 @@ import "preact"; /** @jsxRuntime automatic @jsxImportSource preact */ import type { DebugOperation } from "@starbeam/debug"; -import type { Timestamp } from "@starbeam/interfaces"; +import type { Timestamp } from "@starbeam/interfaces/index.js"; import { TIMELINE } from "@starbeam/runtime"; import type { JSX } from "preact"; import { useMemo, useState } from "preact/hooks"; @@ -10,12 +10,13 @@ import { useMemo, useState } from "preact/hooks"; import { CellConsumeLine, CellUpdateLine } from "./cell.js"; import css from "./css/log.css?inline"; import { FrameConsumeLine } from "./frame.js"; -import { type UpdatePane, Pane, UiPane } from "./pane.js"; +import type {UpdatePane} from "./pane.js"; +import { Pane, UiPane } from "./pane.js"; import type { DevtoolsOptions } from "./shared.js"; import { LogLine } from "./ui.js"; export function DevtoolsLog({ - options = {}, + options = {} }: { options?: DevtoolsOptions; }): JSX.Element { diff --git a/packages/x/devtool/src/single/single-reactive.tsx b/packages/x/devtool/src/single/single-reactive.tsx index 38cb6c36..6281f9bf 100644 --- a/packages/x/devtool/src/single/single-reactive.tsx +++ b/packages/x/devtool/src/single/single-reactive.tsx @@ -6,11 +6,12 @@ import type { Description, } from "@starbeam/debug"; import type { CellTag } from "@starbeam/interfaces"; +import type { Tagged } from "@starbeam/runtime"; +import { TIMELINE } from "@starbeam/runtime"; import { getTag } from "@starbeam/tags"; -import { taggedDescription } from "@starbeam/tags"; -import { type Tagged, TIMELINE } from "@starbeam/runtime"; import { isPresent, verified } from "@starbeam/verify"; -import { type JSX, render } from "preact"; +import type { JSX } from "preact"; +import { render } from "preact"; export function DevtoolsFor(props: { reactive: Tagged; diff --git a/packages/x/store/package.json b/packages/x/store/package.json index 7ec93a72..2d09ae37 100644 --- a/packages/x/store/package.json +++ b/packages/x/store/package.json @@ -26,8 +26,10 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/collections": "workspace:^", "@starbeam/debug": "workspace:^", - "@starbeam/js": "workspace:^" + "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^" }, "devDependencies": { "@starbeam-dev/build-support": "workspace:*" diff --git a/packages/x/store/src/flat.ts b/packages/x/store/src/flat.ts index b58b1bf7..a232d236 100644 --- a/packages/x/store/src/flat.ts +++ b/packages/x/store/src/flat.ts @@ -1,5 +1,3 @@ -import { entryPoint } from "@starbeam/debug"; - import type { AggregateRow, AggregatorFor, @@ -39,7 +37,7 @@ export abstract class FlatRows } [Symbol.iterator](): IterableIterator["Row"]> { - return entryPoint(() => this.rows[Symbol.iterator]()); + return this.rows[Symbol.iterator](); } } @@ -235,17 +233,15 @@ export class Query extends FlatRows { } get rows(): TableTypesFor["Row"][] { - return entryPoint(() => { - const table = this.#rows; - const rows = [...table.rows]; - const filtered = rows.filter((row) => this.#filter.matches(row)); - - if (this.#sort) { - return filtered.sort(this.#sort); - } else { - return filtered; - } - }); + const table = this.#rows; + const rows = [...table.rows]; + const filtered = rows.filter((row) => this.#filter.matches(row)); + + if (this.#sort) { + return filtered.sort(this.#sort); + } else { + return filtered; + } } } diff --git a/packages/x/store/src/table.ts b/packages/x/store/src/table.ts index 45e5026f..76f17c37 100644 --- a/packages/x/store/src/table.ts +++ b/packages/x/store/src/table.ts @@ -1,5 +1,6 @@ -import { type Description, descriptionFrom, entryPoint } from "@starbeam/debug"; -import { reactive } from "@starbeam/js"; +import { reactive } from "@starbeam/collections"; +import type { Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/reactive"; import type { Groups } from "./flat.js"; import { FlatRows } from "./flat.js"; @@ -30,14 +31,11 @@ export class Table extends FlatRows { name?: string; } ): Table { - const description = descriptionFrom({ - type: "formula", - api: { - package: "internal", - name: "Table", - }, - fromUser: definition.name ?? definition.model?.name ?? "table", - }); + const description = RUNTIME.Desc?.( + "collection", + definition.name ?? definition.model?.name, + "Table.create" + ); return new Table( { @@ -52,11 +50,11 @@ export class Table extends FlatRows { #id = INITIAL_ID; readonly #definition: TableDefinition>; readonly #rows: Map["Row"]>; - readonly #description: Description; + readonly #description: Description | undefined; private constructor( definition: TableDefinition>, - description: Description + description: Description | undefined ) { super(); this.#rows = reactive.Map(description); @@ -69,7 +67,7 @@ export class Table extends FlatRows { } get rows(): TableTypesFor["Row"][] { - return entryPoint(() => [...this.#rows.values()]); + return [...this.#rows.values()]; } append( @@ -99,17 +97,6 @@ export class Table extends FlatRows { } } -// export type Table = T extends TableTypes -// ? TableImpl -// : TableImpl<{ -// Columns: T; -// Row: { id: string } & T; -// }>; - -// export const Table = { -// create: TableImpl.create, -// }; - type ColumnName = keyof C; export type Model = ( diff --git a/packages/x/vanilla/package.json b/packages/x/vanilla/package.json index 9fd1cd67..bfdafbbd 100644 --- a/packages/x/vanilla/package.json +++ b/packages/x/vanilla/package.json @@ -27,6 +27,7 @@ }, "dependencies": { "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" }, diff --git a/packages/x/vanilla/src/dom.ts b/packages/x/vanilla/src/dom.ts index 73e6eedd..6756241a 100644 --- a/packages/x/vanilla/src/dom.ts +++ b/packages/x/vanilla/src/dom.ts @@ -1,6 +1,5 @@ -import type { Description } from "@starbeam/debug"; -import { descriptionFrom } from "@starbeam/debug"; -import type { Reactive } from "@starbeam/runtime"; +import type { Description, Reactive } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/runtime"; import { Formula, LIFETIME } from "@starbeam/universal"; import { Cursor } from "./cursor.js"; @@ -21,7 +20,7 @@ function Render( cleanup: () => void; update: () => void; }, - description: Description + description: Description | undefined ): (into: T) => OutputConstructor { return (into: T) => { return { @@ -46,29 +45,19 @@ export function Text( text: Reactive, description?: string | Description ): ContentNode { - return Render( - ({ into }) => { - const node = into.insert(into.document.createTextNode(text.read())); - - return { - cleanup: () => { - node.remove(); - }, - - update: () => { - node.textContent = text.read(); - }, - }; - }, - descriptionFrom({ - type: "resource", - api: { - package: "@starbeam/dom", - name: "Text", + return Render(({ into }) => { + const node = into.insert(into.document.createTextNode(text.read())); + + return { + cleanup: () => { + node.remove(); }, - fromUser: description, - }) - ); + + update: () => { + node.textContent = text.read(); + }, + }; + }, RUNTIME.Desc?.("resource", description, "Text")); } class FragmentRange { @@ -125,14 +114,7 @@ export function Fragment( nodes: ContentNode[], description?: string | Description ): ContentNode { - const desc = descriptionFrom({ - type: "resource", - api: { - package: "@starbeam/dom", - name: "Fragment", - }, - fromUser: description, - }); + const desc = RUNTIME.Desc?.("resource", description, "Fragment"); return Render(({ into, owner }) => { const start = placeholder(into.document); @@ -168,42 +150,32 @@ export function Attr( value: Reactive, description?: string | Description ): AttrNode { - return Render( - ({ into }) => { - const current = value.read(); - - if (typeof current === "string") { - into.setAttribute(name, current); - } else if (current === true) { - into.setAttribute(name, ""); - } + return Render(({ into }) => { + const current = value.read(); + + if (typeof current === "string") { + into.setAttribute(name, current); + } else if (current === true) { + into.setAttribute(name, ""); + } - return { - cleanup: () => { + return { + cleanup: () => { + into.removeAttribute(name); + }, + update: () => { + const next = value.read(); + + if (typeof next === "string") { + into.setAttribute(name, next); + } else if (next === true) { + into.setAttribute(name, ""); + } else if (next === false) { into.removeAttribute(name); - }, - update: () => { - const next = value.read(); - - if (typeof next === "string") { - into.setAttribute(name, next); - } else if (next === true) { - into.setAttribute(name, ""); - } else if (next === false) { - into.removeAttribute(name); - } - }, - }; - }, - descriptionFrom({ - type: "resource", - api: { - package: "@starbeam/dom", - name: "Attr", + } }, - fromUser: description, - }) - ); + }; + }, RUNTIME.Desc?.("resource", description, "Attr")); } export function Element( @@ -218,46 +190,36 @@ export function Element( }, description?: Description | string ): ContentNode { - return Render( - ({ into, owner }) => { - const element = into.document.createElement(tag); - const elementCursor = Cursor.appendTo(element); + return Render(({ into, owner }) => { + const element = into.document.createElement(tag); + const elementCursor = Cursor.appendTo(element); - const renderAttributes: Rendered[] = []; + const renderAttributes: Rendered[] = []; - for (const attrConstructor of attributes) { - const attr = attrConstructor(element).create({ owner }); - renderAttributes.push(attr); - } + for (const attrConstructor of attributes) { + const attr = attrConstructor(element).create({ owner }); + renderAttributes.push(attr); + } + + const fragment = Array.isArray(body) ? Fragment(body) : body; + const renderBody = fragment(elementCursor).create({ owner }); + + into.insert(element); - const fragment = Array.isArray(body) ? Fragment(body) : body; - const renderBody = fragment(elementCursor).create({ owner }); - - into.insert(element); - - return { - cleanup: () => { - element.remove(); - }, - - update: () => { - for (const attr of renderAttributes) { - attr.poll(); - } - - renderBody.poll(); - }, - }; - }, - descriptionFrom({ - type: "resource", - api: { - package: "@starbeam/dom", - name: "Element", + return { + cleanup: () => { + element.remove(); + }, + + update: () => { + for (const attr of renderAttributes) { + attr.poll(); + } + + renderBody.poll(); }, - fromUser: description, - }) - ); + }; + }, RUNTIME.Desc?.("resource", description, "Element")); } Element.Attr = Attr; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8876d50d..f16667be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -170,9 +170,9 @@ importers: demos/preact: dependencies: - '@starbeam/js': + '@starbeam/collections': specifier: workspace:^ - version: link:../../packages/universal/js + version: link:../../packages/universal/collections '@starbeam/preact': specifier: workspace:^ version: link:../../packages/preact/preact @@ -204,9 +204,9 @@ importers: demos/preact-hello-world: dependencies: - '@starbeam/js': + '@starbeam/collections': specifier: workspace:^ - version: link:../../packages/universal/js + version: link:../../packages/universal/collections '@starbeam/preact': specifier: workspace:^ version: link:../../packages/preact/preact @@ -241,9 +241,9 @@ importers: demos/react: dependencies: - '@starbeam/js': + '@starbeam/collections': specifier: workspace:^ - version: link:../../packages/universal/js + version: link:../../packages/universal/collections '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react @@ -281,12 +281,12 @@ importers: demos/react-jsnation: dependencies: + '@starbeam/collections': + specifier: workspace:^ + version: link:../../packages/universal/collections '@starbeam/debug': specifier: workspace:^ version: link:../../packages/universal/debug - '@starbeam/js': - specifier: workspace:^ - version: link:../../packages/universal/js '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react @@ -329,7 +329,7 @@ importers: version: link:../../../packages/react/test-utils '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../../packages/universal/test-utils + version: link:../../../workspace/test-utils react: specifier: '*' version: 18.2.0 @@ -349,15 +349,21 @@ importers: demos/react-lite-query: dependencies: + '@starbeam/collections': + specifier: workspace:^ + version: link:../../packages/universal/collections '@starbeam/debug': specifier: workspace:^ version: link:../../packages/universal/debug - '@starbeam/js': + '@starbeam/interfaces': specifier: workspace:^ - version: link:../../packages/universal/js + version: link:../../packages/universal/interfaces '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../packages/universal/runtime '@starbeam/universal': specifier: workspace:^ version: link:../../packages/universal/universal @@ -398,9 +404,9 @@ importers: demos/react-query: dependencies: - '@starbeam/js': + '@starbeam/collections': specifier: workspace:^ - version: link:../../packages/universal/js + version: link:../../packages/universal/collections '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react @@ -453,9 +459,9 @@ importers: demos/react-stock-ticker: dependencies: - '@starbeam/js': + '@starbeam/collections': specifier: workspace:^ - version: link:../../packages/universal/js + version: link:../../packages/universal/collections '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react @@ -624,7 +630,7 @@ importers: version: link:.. '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../../universal/test-utils + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:../../../universal/debug @@ -674,7 +680,7 @@ importers: dependencies: '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../../universal/test-utils + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:../../../universal/debug @@ -714,7 +720,7 @@ importers: version: link:../../preact-testing-utils '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../../universal/test-utils + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:../../../universal/debug @@ -752,6 +758,9 @@ importers: packages/react/react: dependencies: + '@starbeam/collections': + specifier: workspace:^ + version: link:../../universal/collections '@starbeam/core-utils': specifier: workspace:^ version: link:../../universal/core-utils @@ -761,9 +770,6 @@ importers: '@starbeam/interfaces': specifier: workspace:^ version: link:../../universal/interfaces - '@starbeam/js': - specifier: workspace:^ - version: link:../../universal/js '@starbeam/modifier': specifier: workspace:^ version: link:../../universal/modifier @@ -818,7 +824,7 @@ importers: version: link:../../test-utils '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../../universal/test-utils + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:../../../universal/debug @@ -848,13 +854,19 @@ importers: dependencies: '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../universal/test-utils + version: link:../../../workspace/test-utils '@starbeam/core-utils': specifier: workspace:^ version: link:../../universal/core-utils '@starbeam/debug': specifier: workspace:^ version: link:../../universal/debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../universal/interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../universal/reactive '@starbeam/shared': specifier: workspace:^ version: link:../../universal/shared @@ -916,6 +928,46 @@ importers: specifier: ^20.0.3 version: 20.0.3 + packages/universal/collections: + dependencies: + '@starbeam/debug': + specifier: workspace:^ + version: link:../debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive + '@starbeam/runtime': + specifier: workspace:^ + version: link:../runtime + '@starbeam/shared': + specifier: workspace:^ + version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags + '@starbeam/universal': + specifier: workspace:^ + version: link:../universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../verify + devDependencies: + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../../../workspace/build + + packages/universal/collections/tests: + dependencies: + '@starbeam/collections': + specifier: workspace:^ + version: link:.. + '@starbeam/universal': + specifier: workspace:^ + version: link:../../universal + packages/universal/core: dependencies: '@starbeam/universal': @@ -949,9 +1001,15 @@ importers: '@starbeam/interfaces': specifier: workspace:^ version: link:../interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../reactive '@starbeam/shared': specifier: workspace:^ version: link:../shared + '@starbeam/tags': + specifier: workspace:^ + version: link:../tags '@starbeam/verify': specifier: workspace:^ version: link:../verify @@ -977,6 +1035,9 @@ importers: packages/universal/debug/tests: dependencies: + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:.. @@ -990,7 +1051,7 @@ importers: specifier: workspace:^ version: link:../shared - packages/universal/js: + packages/universal/modifier: dependencies: '@starbeam/debug': specifier: workspace:^ @@ -1001,43 +1062,6 @@ importers: '@starbeam/reactive': specifier: workspace:^ version: link:../reactive - '@starbeam/runtime': - specifier: workspace:^ - version: link:../runtime - '@starbeam/shared': - specifier: workspace:^ - version: link:../shared - '@starbeam/tags': - specifier: workspace:^ - version: link:../tags - '@starbeam/universal': - specifier: workspace:^ - version: link:../universal - '@starbeam/verify': - specifier: workspace:^ - version: link:../verify - devDependencies: - '@starbeam-dev/build-support': - specifier: workspace:* - version: link:../../../workspace/build - - packages/universal/js/tests: - dependencies: - '@starbeam/js': - specifier: workspace:^ - version: link:.. - '@starbeam/universal': - specifier: workspace:^ - version: link:../../universal - - packages/universal/modifier: - dependencies: - '@starbeam/debug': - specifier: workspace:^ - version: link:../debug - '@starbeam/interfaces': - specifier: workspace:^ - version: link:../interfaces '@starbeam/shared': specifier: workspace:^ version: link:../shared @@ -1063,9 +1087,6 @@ importers: '@starbeam/core-utils': specifier: workspace:^ version: link:../core-utils - '@starbeam/debug': - specifier: workspace:^ - version: link:../debug '@starbeam/interfaces': specifier: workspace:^ version: link:../interfaces @@ -1127,16 +1148,16 @@ importers: dependencies: '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../test-utils + version: link:../../../../workspace/test-utils + '@starbeam/collections': + specifier: workspace:^ + version: link:../../collections '@starbeam/debug': specifier: workspace:^ version: link:../../debug '@starbeam/interfaces': specifier: workspace:^ version: link:../../interfaces - '@starbeam/js': - specifier: workspace:^ - version: link:../../js '@starbeam/reactive': specifier: workspace:^ version: link:../../reactive @@ -1228,16 +1249,16 @@ importers: dependencies: '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../test-utils + version: link:../../../../workspace/test-utils + '@starbeam/collections': + specifier: workspace:^ + version: link:../../collections '@starbeam/debug': specifier: workspace:^ version: link:../../debug '@starbeam/interfaces': specifier: workspace:^ version: link:../../interfaces - '@starbeam/js': - specifier: workspace:^ - version: link:../../js '@starbeam/reactive': specifier: workspace:^ version: link:../../reactive @@ -1268,9 +1289,9 @@ importers: packages/universal/tags: dependencies: - '@starbeam/debug': + '@starbeam/core-utils': specifier: workspace:^ - version: link:../debug + version: link:../core-utils '@starbeam/interfaces': specifier: workspace:^ version: link:../interfaces @@ -1282,22 +1303,6 @@ importers: specifier: workspace:* version: link:../../../workspace/build - packages/universal/test-utils: - dependencies: - '@starbeam/runtime': - specifier: workspace:^ - version: link:../runtime - '@starbeam/universal': - specifier: workspace:^ - version: link:../universal - '@starbeam/verify': - specifier: workspace:^ - version: link:../verify - devDependencies: - '@starbeam-dev/build-support': - specifier: workspace:* - version: link:../../../workspace/build - packages/universal/universal: dependencies: '@starbeam/core-utils': @@ -1337,12 +1342,12 @@ importers: packages/universal/universal/tests: dependencies: + '@starbeam/collections': + specifier: workspace:^ + version: link:../../collections '@starbeam/debug': specifier: workspace:^ version: link:../../debug - '@starbeam/js': - specifier: workspace:^ - version: link:../../js '@starbeam/resource': specifier: workspace:^ version: link:../../resource @@ -1355,7 +1360,7 @@ importers: devDependencies: '@starbeam-workspace/test-utils': specifier: workspace:^ - version: link:../../test-utils + version: link:../../../../workspace/test-utils packages/universal/verify: dependencies: @@ -1424,12 +1429,18 @@ importers: packages/x/store: dependencies: + '@starbeam/collections': + specifier: workspace:^ + version: link:../../universal/collections '@starbeam/debug': specifier: workspace:^ version: link:../../universal/debug - '@starbeam/js': + '@starbeam/interfaces': specifier: workspace:^ - version: link:../../universal/js + version: link:../../universal/interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../universal/reactive devDependencies: '@starbeam-dev/build-support': specifier: workspace:* @@ -1455,6 +1466,9 @@ importers: '@starbeam/debug': specifier: workspace:^ version: link:../../universal/debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../universal/interfaces '@starbeam/runtime': specifier: workspace:^ version: link:../../universal/runtime @@ -1895,6 +1909,22 @@ importers: specifier: workspace:^ version: link:../../@types/shell-escape-tag + workspace/test-utils: + dependencies: + '@starbeam/runtime': + specifier: workspace:^ + version: link:../../packages/universal/runtime + '@starbeam/universal': + specifier: workspace:^ + version: link:../../packages/universal/universal + '@starbeam/verify': + specifier: workspace:^ + version: link:../../packages/universal/verify + devDependencies: + '@starbeam-dev/build-support': + specifier: workspace:* + version: link:../build + workspace/workspace: dependencies: '@starbeam-workspace/paths': diff --git a/vitest.config.ts b/vitest.config.ts index bf77e22e..549acb2c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -5,6 +5,7 @@ const env = process.env["STARBEAM_TRACE"] ? { STARBEAM_TRACE: "true" } : {}; export default defineConfig({ test: { + includeSource: ["packages/*/*/src/**/*.ts"], exclude: ["**/node_modules/**", "demos/**", "**/dist/**"], env, }, diff --git a/workspace/build/src/config.js b/workspace/build/src/config.js index cffcbb93..7b45af01 100644 --- a/workspace/build/src/config.js +++ b/workspace/build/src/config.js @@ -252,9 +252,9 @@ export class Package { /** * @param {ImportMeta | string} meta - * @returns {ViteExport} + * @returns {Promise} */ - static viteConfig(meta) { + static async viteConfig(meta) { const pkg = Package.at(meta); if (pkg) return pkg.#viteConfig(); @@ -312,9 +312,9 @@ export class Package { } /** - * @returns {import("./config.js").ViteExport} + * @returns {Promise} */ - #viteConfig() { + async #viteConfig() { return viteConfig({ plugins: [ VitePluginFonts({ @@ -493,7 +493,7 @@ function mapExternal(inline) { /** * @param {import("./config.js").ViteExport} config */ -function viteConfig(config) { +async function viteConfig(config) { return config; } diff --git a/workspace/eslint/src/base.js b/workspace/eslint/src/base.js index 6225c559..cd2c6415 100644 --- a/workspace/eslint/src/base.js +++ b/workspace/eslint/src/base.js @@ -140,4 +140,7 @@ exports.rules = { }, ], "import/no-relative-packages": "error", + "import/first": "error", + "import/newline-after-import": "error", + "import/no-duplicates": "error", }; diff --git a/workspace/reporter/src/table.ts b/workspace/reporter/src/table.ts index 21eea685..941622d2 100644 --- a/workspace/reporter/src/table.ts +++ b/workspace/reporter/src/table.ts @@ -1,6 +1,6 @@ import { isPresent, - mapOrNullifyEmpty, + mapIfPresent, objectHasKeys, } from "@starbeam/core-utils"; import { DisplayStruct } from "@starbeam-workspace/shared"; @@ -106,20 +106,20 @@ class Columns { } headers(state: LoggerState): string[] | undefined { - return mapOrNullifyEmpty( + return mapIfPresent( this.#columns, (column) => column.header(state) ?? "" ); } columnWidths(rows: Cell[][], state: LoggerState): number[] | undefined { - return mapOrNullifyEmpty(this.#columns, (column, index) => + return mapIfPresent(this.#columns, (column, index) => column.maxWidth(rows.map((row) => row[index]).filter(isPresent), state) ); } get justifications(): Table.HorizontalAlignment[] | undefined { - return mapOrNullifyEmpty(this.#columns, (column) => column.justification); + return mapIfPresent(this.#columns, (column) => column.justification); } } diff --git a/packages/universal/js/.eslintrc.json b/workspace/test-utils/.eslintrc.json similarity index 75% rename from packages/universal/js/.eslintrc.json rename to workspace/test-utils/.eslintrc.json index 3b66e573..631eb2e8 100644 --- a/packages/universal/js/.eslintrc.json +++ b/workspace/test-utils/.eslintrc.json @@ -5,7 +5,7 @@ "extends": ["plugin:@starbeam/tight"], "files": ["index.ts", "src/**/*.ts"], "parserOptions": { - "project": "packages/universal/js/tsconfig.json" + "project": "workspace/test-utils/tsconfig.json" } } ] diff --git a/packages/universal/test-utils/.npmrc b/workspace/test-utils/.npmrc similarity index 100% rename from packages/universal/test-utils/.npmrc rename to workspace/test-utils/.npmrc diff --git a/packages/universal/test-utils/index.ts b/workspace/test-utils/index.ts similarity index 100% rename from packages/universal/test-utils/index.ts rename to workspace/test-utils/index.ts diff --git a/packages/universal/test-utils/package.json b/workspace/test-utils/package.json similarity index 100% rename from packages/universal/test-utils/package.json rename to workspace/test-utils/package.json diff --git a/packages/universal/test-utils/rollup.config.mjs b/workspace/test-utils/rollup.config.mjs similarity index 100% rename from packages/universal/test-utils/rollup.config.mjs rename to workspace/test-utils/rollup.config.mjs diff --git a/packages/universal/test-utils/src/test-resource.ts b/workspace/test-utils/src/test-resource.ts similarity index 100% rename from packages/universal/test-utils/src/test-resource.ts rename to workspace/test-utils/src/test-resource.ts diff --git a/packages/universal/test-utils/src/utils.ts b/workspace/test-utils/src/utils.ts similarity index 100% rename from packages/universal/test-utils/src/utils.ts rename to workspace/test-utils/src/utils.ts diff --git a/packages/universal/test-utils/src/vitest.ts b/workspace/test-utils/src/vitest.ts similarity index 100% rename from packages/universal/test-utils/src/vitest.ts rename to workspace/test-utils/src/vitest.ts diff --git a/workspace/test-utils/tsconfig.json b/workspace/test-utils/tsconfig.json new file mode 100644 index 00000000..2ea23771 --- /dev/null +++ b/workspace/test-utils/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../dist/types", + "declarationMap": true, + "outDir": "../../dist/packages", + "types": ["../../packages/env"] + }, + "exclude": ["dist/**/*"] +} From fcdd2a9879769c9a78e20729685b47fcc1084df7 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 6 Apr 2023 21:13:32 -0700 Subject: [PATCH 28/46] Cleaned up @starbeam/reactive --- packages/universal/interfaces/src/protocol.ts | 4 + .../universal/reactive/src/primitives/base.ts | 19 --- .../reactive/src/primitives/cached.ts | 112 +++++++----------- .../universal/reactive/src/primitives/cell.ts | 100 +++++++--------- .../src/primitives/formula-lifecycle.ts | 89 +++++--------- .../reactive/src/primitives/formula.ts | 59 ++++----- .../reactive/src/primitives/marker.ts | 46 +++---- .../reactive/src/primitives/static.ts | 40 ++----- .../reactive/src/primitives/utils.ts | 26 ++-- packages/universal/service/tests/package.json | 2 +- 10 files changed, 180 insertions(+), 317 deletions(-) delete mode 100644 packages/universal/reactive/src/primitives/base.ts diff --git a/packages/universal/interfaces/src/protocol.ts b/packages/universal/interfaces/src/protocol.ts index 83719022..adba4119 100644 --- a/packages/universal/interfaces/src/protocol.ts +++ b/packages/universal/interfaces/src/protocol.ts @@ -155,8 +155,12 @@ export interface TaggedReactive export interface ReactiveCell extends ReactiveValue { current: T; + set: (value: T, caller?: CallStack) => void; + update: (fn: (value: T) => T, caller?: CallStack) => void; + freeze: () => void; } export interface ReactiveFormula extends ReactiveValue { + (): T; readonly current: T; } diff --git a/packages/universal/reactive/src/primitives/base.ts b/packages/universal/reactive/src/primitives/base.ts deleted file mode 100644 index 85b705bb..00000000 --- a/packages/universal/reactive/src/primitives/base.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { readonly } from "@starbeam/core-utils"; -import type { CallStack, Tag } from "@starbeam/interfaces"; -import { TAG } from "@starbeam/shared"; - -import { RUNTIME } from "../runtime.js"; - -export abstract class ReactivePrimitive { - declare readonly [TAG]: T; - - constructor(tag: T) { - readonly(this, TAG, tag); - } - - abstract read(caller?: CallStack): V; - - get current(): V { - return this.read(RUNTIME.callerStack?.()); - } -} diff --git a/packages/universal/reactive/src/primitives/cached.ts b/packages/universal/reactive/src/primitives/cached.ts index a3eff56a..dba3f7ed 100644 --- a/packages/universal/reactive/src/primitives/cached.ts +++ b/packages/universal/reactive/src/primitives/cached.ts @@ -1,13 +1,7 @@ -import type { - Description, - FormulaTag, - ReactiveFormula, -} from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { createFormulaTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; -import type { Formula } from "./formula.js"; import { type FinalizedFormula, FormulaLifecycle, @@ -19,84 +13,60 @@ import { WrapFn, } from "./utils.js"; -interface Last { - readonly formula: FinalizedFormula; - value: T; -} +export function CachedFormula( + compute: () => T, + options?: SugaryPrimitiveOptions +): FormulaFn { + const { description } = toOptions(options); + const desc = RUNTIME.debug?.desc("formula", description); -class FormulaImpl implements ReactiveFormula { - static create = ( - compute: () => T, - options?: SugaryPrimitiveOptions - ): FormulaFn => { - const { description } = toOptions(options); - const formula = new FormulaImpl( - compute, - RUNTIME.debug?.desc("formula", description) - ); + let last: Last | null = null; - return WrapFn(formula); - }; + const tag = createFormulaTag(desc, () => + last === null ? new Set() : last.formula.children() + ); - declare readonly [TAG]: FormulaTag; - readonly #compute: () => T; - #last: Last | null; + function evaluate(): T { + if (last === null) { + const lifecycle = FormulaLifecycle(); + const value = compute(); + const formula = lifecycle.done(); - private constructor(compute: () => T, description: Description | undefined) { - this.#last = null; - this.#compute = compute; - this[TAG] = createFormulaTag(description, () => { - if (this.#last === null) return new Set(); - return this.#last.formula.children(); - }); - } + last = { formula, value }; - get current(): T { - return this.read(RUNTIME.callerStack?.()); - } + tag.markInitialized(); + RUNTIME.subscriptions.update(tag); - read(_caller = RUNTIME.callerStack?.()): T { - const value = this.#evaluate(); - RUNTIME.autotracking.consume(this[TAG]); - return value; - } + return value; + } else if (last.formula.isStale()) { + const lifecycle = last.formula.update(); + const value = (last.value = compute()); + lifecycle.done(); + RUNTIME.subscriptions.update(tag); - #evaluate(): T { - if (this.#last === null) { - return this.#initialize(); - } else if (this.#last.formula.isStale()) { - return this.#update(this.#last); + // last.value = value; + return value; } else { - return this.#last.value; + return last.value; } } - #initialize(): T { - const lifecycle = FormulaLifecycle(this[TAG].description); - const value = this.#compute(); - const formula = lifecycle.done(); - - this.#last = { - formula, - value, - }; - - this[TAG].markInitialized(); - RUNTIME.subscriptions.update(this[TAG]); - + function read(_caller = RUNTIME.callerStack?.()): T { + const value = evaluate(); + RUNTIME.autotracking.consume(tag); return value; } - #update(last: Last): T { - const lifecycle = last.formula.update(); - const value = this.#compute(); - lifecycle.done(); - RUNTIME.subscriptions.update(this[TAG]); - - last.value = value; - return value; - } + return WrapFn({ + [TAG]: tag, + read, + get current(): T { + return read(RUNTIME.callerStack?.()); + }, + }); } -export const CachedFormula = FormulaImpl.create; -export type CachedFormula = Formula; +interface Last { + readonly formula: FinalizedFormula; + value: T; +} diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index 80d72722..a91d7e7c 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -1,76 +1,56 @@ -import { readonly } from "@starbeam/core-utils"; -import type { - CellTag as ICellTag, - Description, - ReactiveCell, -} from "@starbeam/interfaces"; +import type { Description, ReactiveCell } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { createCellTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; -import { - type DescriptionOption, - isDescriptionOption, - type PrimitiveOptions, -} from "./utils.js"; +import { isDescriptionOption, type PrimitiveOptions } from "./utils.js"; -export class CellImpl implements ReactiveCell { - static create = ( - value: T, - options?: CellOptions | DescriptionOption - ): Cell => { - const { description, equals = Object.is } = toCellOptions(options); - return new CellImpl(value, equals, RUNTIME.Desc?.("cell", description)); - }; - - #value: T; - readonly #equals: Equality; - declare readonly [TAG]: ICellTag; - - private constructor( - value: T, - equality: Equality, - description: Description | undefined - ) { - this.#value = value; - this.#equals = equality; - readonly(this, TAG, createCellTag(description)); - } +export type Cell = ReactiveCell; - get current(): T { - return this.read(RUNTIME.callerStack?.()); - } +export function Cell( + value: T, + options?: CellOptions | string | Description | undefined +): ReactiveCell { + const { description, equals = Object.is } = toCellOptions(options); + const desc = RUNTIME.Desc?.("cell", description); + const tag = createCellTag(desc); - set current(value: T) { - this.set(value, RUNTIME.callerStack?.()); - } - - read(_caller = RUNTIME.callerStack?.()): T { - RUNTIME.autotracking.consume(this[TAG]); - return this.#value; - } - - set(value: T, caller = RUNTIME.callerStack?.()): boolean { - if (this.#equals(value, this.#value)) { + const set = (newValue: T, caller = RUNTIME.callerStack?.()): boolean => { + if (equals(value, newValue)) { return false; } - this.#value = value; - this[TAG].update({ caller, runtime: RUNTIME }); + value = newValue; + tag.update({ caller, runtime: RUNTIME }); return true; - } + }; - update(updater: (prev: T) => T, caller = RUNTIME.callerStack?.()) { - this.set(updater(this.#value), caller); - } + const update = (updater: (prev: T) => T, caller = RUNTIME.callerStack?.()) => + set(updater(value), caller); - freeze(): void { - this[TAG].freeze(); - } -} + const read = (_caller = RUNTIME.callerStack?.()): T => { + RUNTIME.autotracking.consume(tag); + return value; + }; + + const freeze = () => { + tag.freeze(); + }; -export const Cell = CellImpl.create; -export type Cell = CellImpl; + return { + [TAG]: tag, + get current(): T { + return read(RUNTIME.callerStack?.()); + }, + set current(value: T) { + set(value, RUNTIME.callerStack?.()); + }, + read, + set, + update, + freeze, + }; +} export type Equality = (a: T, b: T) => boolean; @@ -79,7 +59,7 @@ export interface CellOptions extends PrimitiveOptions { } export function toCellOptions( - options: CellOptions | DescriptionOption + options: CellOptions | Description | string | undefined ): CellOptions { return isDescriptionOption(options) ? { description: options } : options; } diff --git a/packages/universal/reactive/src/primitives/formula-lifecycle.ts b/packages/universal/reactive/src/primitives/formula-lifecycle.ts index c53d7d31..4d05c638 100644 --- a/packages/universal/reactive/src/primitives/formula-lifecycle.ts +++ b/packages/universal/reactive/src/primitives/formula-lifecycle.ts @@ -1,75 +1,48 @@ -import type { - ActiveFrame, - Description, - Expand, - Tag, - Timestamp, -} from "@starbeam/interfaces"; +import type { Tag } from "@starbeam/interfaces"; import { lastUpdated, NOW } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; -import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; -export class InitializingFormulaImpl { - static start = (options?: SugaryPrimitiveOptions): InitializingFormula => { - const { description } = toOptions(options); - const active = RUNTIME.autotracking.start(); - return new InitializingFormulaImpl( - active, - RUNTIME.Desc?.("formula", description) - ); - }; - - readonly #active: ActiveFrame; - readonly #description: Description | undefined; - - private constructor( - active: () => Set, - description: Description | undefined - ) { - this.#active = active; - this.#description = description; - } +export function FormulaLifecycle(): InitializingFormula { + const done = RUNTIME.autotracking.start(); - done(): FinalizedFormula { - return new FinalizedFormulaImpl(this.#active(), NOW.now); - } -} - -export const FormulaLifecycle = InitializingFormulaImpl.start; -export type InitializingFormula = Expand; -export type FinalizedFormula = Expand; - -class FinalizedFormulaImpl { - static create = (children: Set): FinalizedFormula => { - return new FinalizedFormulaImpl(children, NOW.now); + return { + done: () => FinalizedFormula(done()), }; +} - #children: Set; - #lastValidated: Timestamp; - - constructor(children: Set, lastValidated: Timestamp) { - this.#children = children; - this.#lastValidated = lastValidated; - } - - isStale(): boolean { - return lastUpdated(...this.#children).gt(this.#lastValidated); - } +function FinalizedFormula(children: Set): FinalizedFormula { + let lastValidated = NOW.now; - children(): Set { - return this.#children; - } + const isStale = () => lastUpdated(...children).gt(lastValidated); - update(): InitializingFormula { + function update() { const done = RUNTIME.autotracking.start(); return { done: () => { - this.#children = done(); - this.#lastValidated = NOW.now; - return this; + children = done(); + lastValidated = NOW.now; + return formula; }, }; } + + const formula = { + isStale, + children: () => children, + update, + }; + + return formula; +} + +export interface InitializingFormula { + readonly done: () => FinalizedFormula; +} + +export interface FinalizedFormula { + readonly isStale: () => boolean; + readonly children: () => Set; + readonly update: () => InitializingFormula; } diff --git a/packages/universal/reactive/src/primitives/formula.ts b/packages/universal/reactive/src/primitives/formula.ts index d4a9e15e..48962239 100644 --- a/packages/universal/reactive/src/primitives/formula.ts +++ b/packages/universal/reactive/src/primitives/formula.ts @@ -1,15 +1,8 @@ -import type { - Description, - Expand, - ReactiveFormula, - TagSet, -} from "@starbeam/interfaces"; -import type { FormulaTag } from "@starbeam/interfaces"; +import type { ReactiveFormula, TagSet } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { createFormulaTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; -import { ReactivePrimitive } from "./base.js"; import { type FormulaFn, type SugaryPrimitiveOptions, @@ -17,38 +10,32 @@ import { WrapFn, } from "./utils.js"; -export class FormulaImpl - extends ReactivePrimitive - implements ReactiveFormula -{ - static create = (compute: () => T, options?: SugaryPrimitiveOptions) => { - const { description } = toOptions(options); - const formula = new FormulaImpl( - compute, - RUNTIME.Desc?.("formula", description) - ); +export type Formula = ReactiveFormula; - return WrapFn(formula); - }; +export function Formula( + compute: () => T, + options?: SugaryPrimitiveOptions +): FormulaFn { + const { description } = toOptions(options); + const desc = RUNTIME.Desc?.("formula", description); + let children: TagSet = new Set(); + const tag = createFormulaTag(desc, () => children); - #compute: () => T; - #children: TagSet = new Set(); + function read(_caller = RUNTIME.callerStack?.()): T { + const { value, tags } = RUNTIME.evaluate(compute); + children = tags; - private constructor(compute: () => T, description: Description | undefined) { - super(createFormulaTag(description, () => this.#children)); - this.#compute = compute; - } - - read(_caller = RUNTIME.callerStack?.()): T { - const { value, tags } = RUNTIME.evaluate(this.#compute); - this.#children = tags; - - this[TAG].markInitialized(); - RUNTIME.subscriptions.update(this[TAG]); + tag.markInitialized(); + RUNTIME.subscriptions.update(tag); return value; } -} -export const Formula = FormulaImpl.create; -export type Formula = Expand> & (() => T); + return WrapFn({ + [TAG]: tag, + read, + get current(): T { + return read(RUNTIME.callerStack?.()); + }, + }); +} diff --git a/packages/universal/reactive/src/primitives/marker.ts b/packages/universal/reactive/src/primitives/marker.ts index 131cac0b..fc15f5bb 100644 --- a/packages/universal/reactive/src/primitives/marker.ts +++ b/packages/universal/reactive/src/primitives/marker.ts @@ -1,40 +1,30 @@ -import { readonly } from "@starbeam/core-utils"; -import { - type CellTag as ICellTag, - type Description, - type Expand, - type Tagged, -} from "@starbeam/interfaces"; +import type { CallStack, CellTag, Tagged } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { createCellTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; import { type SugaryPrimitiveOptions, toOptions } from "./utils.js"; -class MarkerImpl implements Tagged { - static create(this: void, options?: SugaryPrimitiveOptions): MarkerImpl { - const { description } = toOptions(options); - return new MarkerImpl(RUNTIME.Desc?.("cell", description)); - } +export interface Marker extends Tagged { + read: (caller?: CallStack) => void; + mark: (caller?: CallStack) => void; + freeze: () => void; +} - declare readonly [TAG]: ICellTag; +export function Marker(options?: SugaryPrimitiveOptions): Marker { + const { description } = toOptions(options); + const desc = RUNTIME.Desc?.("cell", description); + const tag = createCellTag(desc); - private constructor(description: Description | undefined) { - readonly(this, TAG, createCellTag(description)); - } + const mark = (caller = RUNTIME.callerStack?.()) => { + tag.update({ caller, runtime: RUNTIME }); + }; - read(_caller = RUNTIME.callerStack?.()): void { - RUNTIME.autotracking.consume(this[TAG]); - } + const read = (_caller = RUNTIME.callerStack?.()): void => { + RUNTIME.autotracking.consume(tag); + }; - freeze(): void { - this[TAG].freeze(); - } + const freeze = tag.freeze; - mark(caller = RUNTIME.callerStack?.()): void { - this[TAG].update({ caller, runtime: RUNTIME }); - } + return { [TAG]: tag, read, mark, freeze }; } - -export const Marker = MarkerImpl.create; -export type Marker = Expand; diff --git a/packages/universal/reactive/src/primitives/static.ts b/packages/universal/reactive/src/primitives/static.ts index ece3647e..9f0fef81 100644 --- a/packages/universal/reactive/src/primitives/static.ts +++ b/packages/universal/reactive/src/primitives/static.ts @@ -1,37 +1,19 @@ -import type * as interfaces from "@starbeam/interfaces"; -import type { Description } from "@starbeam/interfaces"; +import type { StaticTag, TaggedReactive } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { createStaticTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; import type { PrimitiveOptions } from "./utils.js"; -export class StaticImpl - implements interfaces.ReactiveValue -{ - static create = ( - value: T, - { description }: PrimitiveOptions = {} - ): StaticImpl => { - return new StaticImpl(value, RUNTIME.Desc?.("static", description)); - }; - - readonly #value: T; - readonly [TAG]: interfaces.StaticTag; - - private constructor(value: T, description: Description | undefined) { - this.#value = value; - this[TAG] = createStaticTag(description); - } +export type Static = TaggedReactive; - get current(): T { - return this.#value; - } - - read(): T { - return this.#value; - } +export function Static( + value: T, + { description }: PrimitiveOptions = {} +): Static { + return { + [TAG]: createStaticTag(RUNTIME.Desc?.("static", description)), + read: () => value, + current: value, + }; } - -export const Static = StaticImpl.create; -export type Static = StaticImpl; diff --git a/packages/universal/reactive/src/primitives/utils.ts b/packages/universal/reactive/src/primitives/utils.ts index 635b9837..2b1224c9 100644 --- a/packages/universal/reactive/src/primitives/utils.ts +++ b/packages/universal/reactive/src/primitives/utils.ts @@ -1,28 +1,22 @@ -import type { - Description, - ReactiveValue, - Tag, - TaggedReactive, -} from "@starbeam/interfaces"; +import type { Description, Tag, TaggedReactive } from "@starbeam/interfaces"; import type { FormulaTag } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { RUNTIME } from "../runtime.js"; export interface PrimitiveOptions { - description?: DescriptionOption; + description?: string | Description | undefined; } -/** - * If a string is passed as options to a primitive, it's the description. - */ -export type DescriptionOption = string | Description | undefined; - -export type SugaryPrimitiveOptions = PrimitiveOptions | DescriptionOption; +export type SugaryPrimitiveOptions = + | PrimitiveOptions + | string + | Description + | undefined; export function isDescriptionOption( options: SugaryPrimitiveOptions -): options is DescriptionOption { +): options is string | Description | undefined { return ( options === undefined || typeof options === "string" || "id" in options ); @@ -48,7 +42,9 @@ export function isFormulaFn(value: unknown): value is FormulaFn { ); } -export function WrapFn(formula: ReactiveValue): FormulaFn { +export function WrapFn( + formula: TaggedReactive +): FormulaFn { // If the formula is *already* a function, we just need a new identity for it, // so we'll wrap it in a simple proxy. // diff --git a/packages/universal/service/tests/package.json b/packages/universal/service/tests/package.json index d1f58dc8..3269cc2c 100644 --- a/packages/universal/service/tests/package.json +++ b/packages/universal/service/tests/package.json @@ -9,9 +9,9 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/collections": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/collections": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", From 2d53269d24a733b142e0696fe1bd986ac030ad81 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 6 Apr 2023 22:17:14 -0700 Subject: [PATCH 29/46] Start cleaning up runtime --- packages/universal/runtime/index.ts | 4 +- packages/universal/runtime/src/timeline/id.ts | 5 - .../universal/runtime/src/timeline/spec.md | 23 ++ .../runtime/src/timeline/subscriptions.ts | 280 +++++++----------- .../universal/runtime/src/timeline/tracker.ts | 2 +- 5 files changed, 127 insertions(+), 187 deletions(-) delete mode 100644 packages/universal/runtime/src/timeline/id.ts create mode 100644 packages/universal/runtime/src/timeline/spec.md diff --git a/packages/universal/runtime/index.ts b/packages/universal/runtime/index.ts index 299fb04f..785ddaac 100644 --- a/packages/universal/runtime/index.ts +++ b/packages/universal/runtime/index.ts @@ -1,4 +1,5 @@ export { type AppContext, CONTEXT } from "./src/context/context.js"; +export { RUNTIME } from "./src/define.js"; export { type CleanupTarget, LIFETIME, @@ -18,6 +19,3 @@ export { AUTOTRACKING_RUNTIME } from "./src/tracking-stack.js"; export type { Tag, Tagged } from "@starbeam/interfaces"; export { TAG } from "@starbeam/shared"; export { getTag, Timestamp } from "@starbeam/tags"; -export type { interfaces }; -import type * as interfaces from "@starbeam/interfaces"; -export { RUNTIME } from "./src/define.js"; diff --git a/packages/universal/runtime/src/timeline/id.ts b/packages/universal/runtime/src/timeline/id.ts deleted file mode 100644 index c5943408..00000000 --- a/packages/universal/runtime/src/timeline/id.ts +++ /dev/null @@ -1,5 +0,0 @@ -let ID = 1; - -export function getID(): string { - return String(ID++); -} diff --git a/packages/universal/runtime/src/timeline/spec.md b/packages/universal/runtime/src/timeline/spec.md new file mode 100644 index 00000000..2cfdc5a2 --- /dev/null +++ b/packages/universal/runtime/src/timeline/spec.md @@ -0,0 +1,23 @@ +A subscription is a weak mapping from individual cells to the subscriptions that +depend on them. This is an interesting problem because consumers can subscribe +to reactive values whose cell depenencies change over time (such as formulas). +We want: + +1. A direct mapping from cells to subscribers. This means that we know + (directly) what subscribers are interested in a cell mutation, allowing us to + do synchronous bookkeeping related to subscribers as mutations occur. +2. A weak mapping from cells to subscribers. If a cell is GC'ed, then no + additional mutations to it can occur, and we don't need to maintain a hard + reference to the cell or its subscribers. We accomplish this by keeping a + weak mapping from formulas to subscriptions, and a second weak mapping from + cells to subscriptions. When a cell is mutated, we have a direct mapping to + the subscriber without additional computations. When a formula is recomputed, + we: +3. get its subscriptions from the mapping. +4. remove the subscriptions from any cells that are no longer dependencies. +5. add the subscriptions to any cells that are now dependencies. + +This makes reading formulas a bit slower, but simplifies cell mutation. This +is a good trade-off, since formula computation is typically scheduled, and +happens in response to potentially many mutations. See [A detailed +description of the approach used here](./subscriptions.md) diff --git a/packages/universal/runtime/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts index 904456a0..23bd5d8c 100644 --- a/packages/universal/runtime/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -6,218 +6,150 @@ import type { SubscriptionTarget, Tag, } from "@starbeam/interfaces"; +import { getTargets } from "@starbeam/tags"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { diff } from "./utils.js"; -import { getTargets } from "@starbeam/tags"; -/** - * A subscription is a weak mapping from individual cells to the subscriptions that depend on them. - * - * This is an interesting problem because consumers can subscribe to reactive values whose cell - * depenencies change over time (such as formulas). - * - * We want: - * - * 1. A direct mapping from cells to subscribers. This means that we know (directly) what - * subscribers are interested in a cell mutation, allowing us to do synchronous bookkeeping - * related to subscribers as mutations occur. - * 2. A weak mapping from cells to subscribers. If a cell is GC'ed, then no additional mutations to - * it can occur, and we don't need to maintain a hard reference to the cell or its subscribers. - * - * We accomplish this by keeping a weak mapping from formulas to subscriptions, and a second weak - * mapping from cells to subscriptions. - * - * When a cell is mutated, we have a direct mapping to the subscriber without additional - * computations. - * - * When a formula is recomputed, we: - * - * 1. get its subscriptions from the mapping. - * 2. remove the subscriptions from any cells that are no longer dependencies. - * 3. add the subscriptions to any cells that are now dependencies. - * - * This makes reading formulas a bit slower, but simplifies cell mutation. This is a good trade-off, - * since formula computation is typically scheduled, and happens in response to potentially many - * mutations. - * - * @see [A detailed description of the approach used here](./subscriptions.md) - */ -export class Subscriptions { - static create(): Subscriptions { - return new Subscriptions(); - } +export interface Subscriptions { + readonly register: (tag: Tag, ready: NotifyReady) => Unsubscribe; + readonly notify: (cel: CellTag) => void; + readonly update: (formula: FormulaTag) => void; +} - readonly #subscriberMap = SubscriberMap.empty(); - readonly #cellMap = CellMap.empty(); - readonly #tdzSubscriptionMap = new WeakMap>(); - - /** - * Register a notification for a reactive value. - * - * - If the reactive value is a cell, the notification will fire whenever the cell is mutated. - * - If the reactive value is a formula, the notification will fire whenever any of the cell's - * dependencies of the formula are mutated. - * - * --- - * TODO: Is it necessary to fire notifications when the formula is recomputed? What if a formula - * has two consumers, and they both read the formula, get dependencies A and B and register - * notifications. The first consumer reads the formula again, producing dependencies B and C, and - * then mutates A. - * - * Current thinking: Since the notifications never fired, that must mean that neither A nor B - * changed. Therefore, re-computing the formula should not have invalidated, so the whole scenario - * is impossible. - * - * However, it probably *is* possible with `PolledFormula`, which intentionally allows a formula - * to be recomputed even if its Starbeam deps haven't changed. One possibility is that we might - * want to restrict `PolledFormula` to its current use-case of a single consumer. Alternatively, - * we may want to fire notifications whenever a `PolledFormula` is recomputed and produces - * different dependencies. - */ - register(tag: Tag, ready: NotifyReady): Unsubscribe { - const unsubscribes = getTargets(tag).map((t) => this.#register(t, ready)); +export function Subscriptions(): Subscriptions { + const subscribers = SubscriberMap(); + const cells = CellMap(); + const tdzSubscriptions = new WeakMap>(); + + function register(tag: Tag, ready: NotifyReady): Unsubscribe { + const unsubscribes = getTargets(tag).map((t) => registerTarget(t, ready)); return () => { for (const unsubscribe of unsubscribes) unsubscribe(); }; } - #register(target: SubscriptionTarget, ready: NotifyReady): Unsubscribe { + function registerTarget(target: SubscriptionTarget, ready: NotifyReady) { if (target.type === "formula" && !target.initialized) { - const set = this.#upsertTdzSubscriptions(target, ready); + const set = upsertTdzSubscriptions(target, ready); // FIXME: Support removal after upgrade return () => { set.delete(ready); }; } else { - const entry = this.#subscriberMap.register(target); - for (const dependency of target.dependencies()) { - this.#cellMap.register(dependency, entry); - } + const entry = subscribers.register(target); + cells.update({ add: new Set(target.dependencies()) }, entry); return entry.subscribe(ready); } } - #upsertTdzSubscriptions( + function upsertTdzSubscriptions( formula: FormulaTag, ready: NotifyReady ): Set { - let tdzSubscriptions = this.#tdzSubscriptionMap.get(formula); + let subscriptions = tdzSubscriptions.get(formula); - if (!tdzSubscriptions) { - tdzSubscriptions = new Set(); - this.#tdzSubscriptionMap.set(formula, tdzSubscriptions); + if (!subscriptions) { + subscriptions = new Set(); + tdzSubscriptions.set(formula, subscriptions); } - tdzSubscriptions.add(ready); - return tdzSubscriptions; + subscriptions.add(ready); + return subscriptions; } - /** - * Notify the subscribers of a particular cell. This happens synchronously during mutation. - */ - notify(mutable: CellTag): void { - this.#cellMap.notify(mutable); + function notify(cell: CellTag): void { + cells.notify(cell); } - /** - * Update the internal mappings for a formula. This happens after a formula was recomputed. It - * results in removing mappings from cells that are no longer dependencies and adding mappings for - * cells that have become dependencies. - */ - update(formula: FormulaTag): void { - const tdzSubscriptions = this.#tdzSubscriptionMap.get(formula); - - if (tdzSubscriptions) { - for (const ready of tdzSubscriptions) { - this.#register(formula, ready); + function update(formula: FormulaTag): void { + const subscriptions = tdzSubscriptions.get(formula); + + if (subscriptions) { + for (const ready of subscriptions) { + registerTarget(formula, ready); } - this.#tdzSubscriptionMap.delete(formula); + tdzSubscriptions.delete(formula); } - const cellMap = this.#cellMap; - - const { add, remove, entry } = this.#subscriberMap.update(formula); - cellMap.remove(remove, entry); - cellMap.add(add, entry); + const { diff, entry } = subscribers.update(formula); + cells.update(diff, entry); } -} -/** - * A mapping from tagged values to their subscriptions. - */ -class SubscriberMap { - static empty(): SubscriberMap { - return new SubscriberMap(); - } + return { + register, + notify, + update, + }; +} - readonly #mapping = new WeakMap(); +function SubscriberMap() { + const mapping = new WeakMap(); - update(formula: FormulaTag): Diff & { entry: ReactiveSubscription } { - const entry = this.#mapping.get(formula); + function update(formula: FormulaTag): { diff: Diff; entry: Entry } { + const entry = mapping.get(formula); if (entry) { - return { ...entry.update(formula), entry }; + return { diff: entry.update(formula), entry }; } else { - const entry = ReactiveSubscription.create(formula); - this.#mapping.set(formula, entry); + const entry = Entry(formula); + mapping.set(formula, entry); return { - add: new Set(formula.dependencies()), - remove: new Set(), + diff: { + add: new Set(formula.dependencies()), + remove: new Set(), + }, entry, }; } } - register(target: Tag): ReactiveSubscription { - let entry = this.#mapping.get(target); + function register(target: Tag) { + let entry = mapping.get(target); if (!entry) { - entry = ReactiveSubscription.create(target); - this.#mapping.set(target, entry); + entry = Entry(target); + mapping.set(target, entry); } return entry; } -} -class ReactiveSubscription { - static create(target: Tag): ReactiveSubscription { - if (typeof target.dependencies !== "function") { - console.log(target); - throw Error("Reactive subscriptions must be created with tags"); - } - const deps = new Set(target.dependencies()); - return new ReactiveSubscription(deps); - } + return { update, register }; +} - #deps: Set; - readonly #ready = new Set(); +interface Entry { + readonly subscribe: (ready: NotifyReady) => Unsubscribe; + readonly notify: (cell: CellTag) => void; + readonly update: (formula: FormulaTag) => Diff; +} - private constructor(deps: Set) { - this.#deps = deps; - } +function Entry(tag: Tag): Entry { + let deps = new Set(tag.dependencies()); + const readySet = new Set(); - subscribe(ready: NotifyReady): Unsubscribe { - this.#ready.add(ready); - return () => this.#ready.delete(ready); + function subscribe(ready: NotifyReady): Unsubscribe { + readySet.add(ready); + return () => readySet.delete(ready); } - notify(internals: CellTag): void { - for (const ready of this.#ready) { - ready(internals); + function notify(cell: CellTag) { + for (const ready of readySet) { + ready(cell); } } - update(frame: FormulaTag): Diff { - const prev = this.#deps; - const next = new Set(frame.dependencies()); - this.#deps = next; + function update(formula: FormulaTag) { + const prev = deps; + const next = new Set(formula.dependencies()); + deps = next; return diff(prev, next); } + + return { subscribe, notify, update }; } /** @@ -226,51 +158,43 @@ class ReactiveSubscription { * When a mutation occurs, the `CellMap` knows exactly which subscriptions it needs to notify, * which keeps the mutation path simple. */ -class CellMap { - static empty(): CellMap { - return new CellMap(); - } +function CellMap() { + const entriesMap = new WeakMap>(); - readonly #entriesMap = new WeakMap>(); + function initialized(cell: CellTag): Set { + let entries = entriesMap.get(cell); - remove(mutables: ReadonlySet, entry: ReactiveSubscription): void { - for (const mutable of mutables) { - this.#entriesMap.get(mutable)?.delete(entry); + if (!entries) { + entries = new Set(); + entriesMap.set(cell, entries); } - } - add(mutables: ReadonlySet, entry: ReactiveSubscription): void { - for (const mutable of mutables) { - this.#initialized(mutable).add(entry); - } + return entries; } - register(mutable: CellTag, entry: ReactiveSubscription): void { - this.#initialized(mutable).add(entry); - } + // function register(cell: CellTag, entry: Entry): void { + // initialized(cell).add(entry); + // } - notify(mutable: CellTag): void { - for (const entry of this.#entries(mutable)) { - entry.notify(mutable); + function update(diff: Partial>, entry: Entry): void { + for (const cell of diff.add ?? []) { + initialized(cell).add(entry); } - } - *#entries(mutable: CellTag): IterableIterator { - const entries = this.#entriesMap.get(mutable); - - if (entries) { - yield* entries; + for (const cell of diff.remove ?? []) { + entriesMap.get(cell)?.delete(entry); } } - #initialized(mutable: CellTag): Set { - let entries = this.#entriesMap.get(mutable); + function notify(cell: CellTag): void { + const entries = entriesMap.get(cell); - if (!entries) { - entries = new Set(); - this.#entriesMap.set(mutable, entries); + if (entries) { + for (const entry of entries) { + entry.notify(cell); + } } - - return entries; } + + return { update, notify }; } diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index 291e8002..f482e24f 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -28,7 +28,7 @@ export class ReactiveError extends Error {} * responsible for notifying the timeline when their dependencies change. */ class Mutations implements SubscriptionRuntime { - readonly #subscriptions = Subscriptions.create(); + readonly #subscriptions = Subscriptions(); readonly #lastPhase: Phase = Phase.read; subscribe(target: Tag, ready: NotifyReady): Unsubscribe { From 0cee00f147906126255cea74534b1786358b55b8 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 6 Apr 2023 22:58:54 -0700 Subject: [PATCH 30/46] Streamling subscriptions --- .../runtime/src/timeline/subscriptions.ts | 219 ++++++++---------- .../universal/runtime/src/timeline/tracker.ts | 2 +- 2 files changed, 99 insertions(+), 122 deletions(-) diff --git a/packages/universal/runtime/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts index 23bd5d8c..a41191e5 100644 --- a/packages/universal/runtime/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -11,122 +11,81 @@ import { getTargets } from "@starbeam/tags"; import type { Unsubscribe } from "../lifetime/object-lifetime.js"; import { diff } from "./utils.js"; -export interface Subscriptions { - readonly register: (tag: Tag, ready: NotifyReady) => Unsubscribe; - readonly notify: (cel: CellTag) => void; - readonly update: (formula: FormulaTag) => void; -} +export class Subscriptions { + static create(): Subscriptions { + return new Subscriptions(); + } -export function Subscriptions(): Subscriptions { - const subscribers = SubscriberMap(); - const cells = CellMap(); - const tdzSubscriptions = new WeakMap>(); + // A mappping from subscribed tags to their subscriptions + readonly #tagSubscriptions = new LazyWeakMap(Subscription); + // A mapping from the current dependencies of subscribed tags to their subscriptions + readonly #cellSubscriptions = new WeakSetMap(); + // A mapping from uninitialized formulas to notifications that should be + // turned into subscriptions when the formula is initialized + readonly #queuedSubscriptions = new WeakSetMap(); - function register(tag: Tag, ready: NotifyReady): Unsubscribe { - const unsubscribes = getTargets(tag).map((t) => registerTarget(t, ready)); + register(tag: Tag, ready: NotifyReady): Unsubscribe { + const unsubscribes = getTargets(tag).map((t) => this.#subscribe(t, ready)); return () => { for (const unsubscribe of unsubscribes) unsubscribe(); }; } - function registerTarget(target: SubscriptionTarget, ready: NotifyReady) { - if (target.type === "formula" && !target.initialized) { - const set = upsertTdzSubscriptions(target, ready); - - // FIXME: Support removal after upgrade - return () => { - set.delete(ready); - }; - } else { - const entry = subscribers.register(target); - cells.update({ add: new Set(target.dependencies()) }, entry); - return entry.subscribe(ready); + notify(cell: CellTag): void { + for (const entry of this.#cellSubscriptions.get(cell)) { + entry.notify(cell); } } - function upsertTdzSubscriptions( - formula: FormulaTag, - ready: NotifyReady - ): Set { - let subscriptions = tdzSubscriptions.get(formula); - - if (!subscriptions) { - subscriptions = new Set(); - tdzSubscriptions.set(formula, subscriptions); + update(formula: FormulaTag): void { + // if there are any queued subscriptions, subscribe them now + for (const ready of this.#queuedSubscriptions.drain(formula)) { + this.#subscribe(formula, ready); } - subscriptions.add(ready); - return subscriptions; - } - - function notify(cell: CellTag): void { - cells.notify(cell); - } + const subscription = this.#tagSubscriptions.get(formula); + const diff = subscription.update(formula); - function update(formula: FormulaTag): void { - const subscriptions = tdzSubscriptions.get(formula); - - if (subscriptions) { - for (const ready of subscriptions) { - registerTarget(formula, ready); - } - tdzSubscriptions.delete(formula); + // add the subscriptions to any new dependencies + for (const cell of diff.add) { + this.#cellSubscriptions.add(cell, subscription); } - const { diff, entry } = subscribers.update(formula); - cells.update(diff, entry); + // remove the subscriptions from any removed dependencies + for (const cell of diff.remove) { + this.#cellSubscriptions.delete(cell, subscription); + } } - return { - register, - notify, - update, - }; -} - -function SubscriberMap() { - const mapping = new WeakMap(); - - function update(formula: FormulaTag): { diff: Diff; entry: Entry } { - const entry = mapping.get(formula); + #subscribe(target: SubscriptionTarget, ready: NotifyReady) { + if (target.type === "formula" && !target.initialized) { + const set = this.#queuedSubscriptions.add(target, ready); - if (entry) { - return { diff: entry.update(formula), entry }; - } else { - const entry = Entry(formula); - mapping.set(formula, entry); - return { - diff: { - add: new Set(formula.dependencies()), - remove: new Set(), - }, - entry, + // FIXME: Support removal after upgrade + return () => { + set.delete(ready); }; - } - } + } else { + const subscription = this.#tagSubscriptions.get(target); - function register(target: Tag) { - let entry = mapping.get(target); + // initialize the subscription with the current target's dependencies + for (const cell of target.dependencies()) { + this.#cellSubscriptions.add(cell, subscription); + } - if (!entry) { - entry = Entry(target); - mapping.set(target, entry); + return subscription.subscribe(ready); } - - return entry; } - - return { update, register }; } -interface Entry { +interface Subscription { readonly subscribe: (ready: NotifyReady) => Unsubscribe; readonly notify: (cell: CellTag) => void; readonly update: (formula: FormulaTag) => Diff; } -function Entry(tag: Tag): Entry { +function Subscription(tag: Tag): Subscription { let deps = new Set(tag.dependencies()); const readySet = new Set(); @@ -136,9 +95,7 @@ function Entry(tag: Tag): Entry { } function notify(cell: CellTag) { - for (const ready of readySet) { - ready(cell); - } + for (const ready of readySet) ready(cell); } function update(formula: FormulaTag) { @@ -152,49 +109,69 @@ function Entry(tag: Tag): Entry { return { subscribe, notify, update }; } -/** - * CellMap keeps track of the current subscriptions for a specific cell. - * - * When a mutation occurs, the `CellMap` knows exactly which subscriptions it needs to notify, - * which keeps the mutation path simple. - */ -function CellMap() { - const entriesMap = new WeakMap>(); - - function initialized(cell: CellTag): Set { - let entries = entriesMap.get(cell); - - if (!entries) { - entries = new Set(); - entriesMap.set(cell, entries); - } +const EMPTY_SET = new Set(); +const EMPTY_SIZE = 0; + +class LazyWeakMap { + readonly #create: (key: K) => V; + readonly #map = new WeakMap(); - return entries; + constructor(create: (key: K) => V) { + this.#create = create; } - // function register(cell: CellTag, entry: Entry): void { - // initialized(cell).add(entry); - // } + get(key: K): V { + let value = this.#map.get(key); - function update(diff: Partial>, entry: Entry): void { - for (const cell of diff.add ?? []) { - initialized(cell).add(entry); + if (!value) { + value = this.#create(key); + this.#map.set(key, value); } - for (const cell of diff.remove ?? []) { - entriesMap.get(cell)?.delete(entry); - } + return value; } - function notify(cell: CellTag): void { - const entries = entriesMap.get(cell); + delete(key: K): void { + this.#map.delete(key); + } +} - if (entries) { - for (const entry of entries) { - entry.notify(cell); - } +class WeakSetMap { + readonly #map = new WeakMap>(); + + add(key: K, value: V): Set { + const set = this.#initialized(key); + set.add(value); + return set; + } + + drain(key: K): Set { + const set = this.#map.get(key); + this.#map.delete(key); + return set ?? (EMPTY_SET as Set); + } + + delete(key: K, value: V): void { + const set = this.#map.get(key); + + if (set) { + set.delete(value); + if (set.size === EMPTY_SIZE) this.#map.delete(key); } } - return { update, notify }; + get(key: K): Set { + return this.#map.get(key) ?? (EMPTY_SET as Set); + } + + #initialized(key: K): Set { + let set = this.#map.get(key); + + if (!set) { + set = new Set(); + this.#map.set(key, set); + } + + return set; + } } diff --git a/packages/universal/runtime/src/timeline/tracker.ts b/packages/universal/runtime/src/timeline/tracker.ts index f482e24f..291e8002 100644 --- a/packages/universal/runtime/src/timeline/tracker.ts +++ b/packages/universal/runtime/src/timeline/tracker.ts @@ -28,7 +28,7 @@ export class ReactiveError extends Error {} * responsible for notifying the timeline when their dependencies change. */ class Mutations implements SubscriptionRuntime { - readonly #subscriptions = Subscriptions(); + readonly #subscriptions = Subscriptions.create(); readonly #lastPhase: Phase = Phase.read; subscribe(target: Tag, ready: NotifyReady): Unsubscribe { From f032421bf38fb059aa5ea01e31b66600e80ed2f9 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Fri, 7 Apr 2023 12:12:24 -0700 Subject: [PATCH 31/46] Clean up usage of changed APIs --- .vscode/settings.json | 8 +- demos/react-jsnation/package.json | 12 +- package.json | 24 +- packages/preact/preact/src/frame.ts | 6 +- packages/react/react/package.json | 6 +- packages/react/react/src/context-provider.ts | 9 +- packages/react/react/src/element.ts | 12 +- packages/react/react/src/use-reactive.ts | 8 +- packages/react/react/src/use-setup.ts | 5 +- .../react/react/tests/use-reactive.spec.ts | 7 +- .../react/react/tests/use-resource.spec.ts | 13 +- .../universal/collections/src/decorator.ts | 2 +- .../universal/collections/tests/array.spec.ts | 6 +- .../collections/tests/object.spec.ts | 10 +- .../universal/collections/tests/set.spec.ts | 4 +- .../universal/collections/tests/support.ts | 5 +- packages/universal/core-utils/src/array.ts | 18 +- .../debug/src/description/debug/describe.ts | 5 +- .../src/description/debug/description.ts | 55 +- .../debug/src/description/interface.ts | 7 - .../universal/debug/src/description/prod.ts | 2 +- .../interfaces/src/debug/debug-runtime.ts | 1 + .../interfaces/src/debug/description.ts | 26 +- packages/universal/interfaces/src/protocol.ts | 6 +- packages/universal/modifier/src/modifier.ts | 10 +- packages/universal/reactive/index.ts | 6 +- .../universal/reactive/src/primitives/cell.ts | 2 +- packages/universal/reactive/src/runtime.ts | 21 +- .../universal/resource/tests/package.json | 6 +- .../runtime/tests/description.spec.ts | 20 + packages/universal/runtime/tests/package.json | 3 +- packages/universal/universal/index.ts | 9 +- .../universal/universal/tests/formula.spec.ts | 19 +- .../universal/universal/tests/package.json | 2 +- .../universal/tests/polled-formula.spec.ts | 17 +- .../universal/tests/variants.spec.ts | 17 +- packages/x/devtool/package.json | 4 +- packages/x/store/tests/aggregating.spec.ts | 8 +- packages/x/store/tests/grouping.spec.ts | 4 +- packages/x/store/tests/query.spec.ts | 22 +- packages/x/store/tests/table.spec.ts | 6 +- packages/x/vanilla/package.json | 1 + packages/x/vanilla/src/dom.ts | 6 +- pnpm-lock.yaml | 1238 +++++++++++------ 44 files changed, 1022 insertions(+), 656 deletions(-) delete mode 100644 packages/universal/debug/src/description/interface.ts create mode 100644 packages/universal/runtime/tests/description.spec.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 5e349907..6d03c09e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,10 +24,10 @@ "eslint.codeActionsOnSave.mode": "all", "eslint.enable": true, - "eslint.format.enable": true, "eslint.lintTask.enable": true, "eslint.lintTask.options": "--cache -c ./.eslintrc.json --max-warnings=0 \"**/*.ts\" \"**/*.tsx\" \"**/*.json\"", "eslint.onIgnoredFiles": "warn", + "eslint.problems.shortenToSingleLine": true, "eslint.quiet": false, "eslint.validate": [ "javascript", @@ -77,13 +77,13 @@ "**/CHANGELOG.md": true, "pnpm-lock.yaml": true }, - "typescript.experimental.tsserver.web.enableProjectWideIntellisense": true, + "testing.automaticallyOpenPeekView": "never", + "typescript.experimental.tsserver.web.enableProjectWideIntellisense": false, "typescript.preferences.importModuleSpecifier": "project-relative", "typescript.preferences.importModuleSpecifierEnding": "js", "typescript.tsdk": "node_modules/typescript/lib", "typescript.tsserver.experimental.enableProjectDiagnostics": true, - "vitest.enable": true, - "testing.automaticallyOpenPeekView": "never" + "vitest.enable": true } diff --git a/demos/react-jsnation/package.json b/demos/react-jsnation/package.json index bb7e1163..77869374 100644 --- a/demos/react-jsnation/package.json +++ b/demos/react-jsnation/package.json @@ -37,19 +37,19 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/debug": "workspace:^", "@starbeam/collections": "workspace:^", + "@starbeam/debug": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/universal": "workspace:^", "purecss": "3.0.0", - "react": "^18.1.0", - "react-dom": "^18.1.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { - "@types/react": "^18.0.26", - "@types/react-dom": "^18.0.10", + "@types/react": "^18.0.33", + "@types/react-dom": "^18.0.11", "@vitest/ui": "*", "vite": "*", - "vite-plugin-fonts": "^0.6.0" + "vite-plugin-fonts": "^0.7.0" } } diff --git a/package.json b/package.json index 714ae5f4..09c37042 100644 --- a/package.json +++ b/package.json @@ -108,25 +108,25 @@ "@babel/eslint-parser": "^7.21.3", "@babel/plugin-proposal-decorators": "^7.21.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.21.0", - "@babel/preset-env": "^7.20.2", + "@babel/plugin-transform-runtime": "^7.21.4", + "@babel/preset-env": "^7.21.4", "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", + "@babel/preset-typescript": "^7.21.4", "@babel/runtime": "^7.21.0", "@changesets/changelog-git": "^0.1.14", "@changesets/cli": "^2.26.1", "@changesets/config": "^2.3.0", "@starbeam/eslint-plugin": "workspace:^1.0.0", "@starbeam-dev/build-support": "workspace:1.0.0", - "@types/eslint": "^8.21.3", - "@types/node": "18.15.5", - "@typescript-eslint/eslint-plugin": "^5.56.0", - "@typescript-eslint/parser": "^5.56.0", + "@types/eslint": "^8.37.0", + "@types/node": "18.15.11", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", "@vitest/ui": "^0.29.8", - "eslint": "^8.36.0", + "eslint": "^8.37.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.8.0", - "eslint-import-resolver-typescript": "^3.5.3", + "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.27.5", "eslint-plugin-jsonc": "^2.7.0", "eslint-plugin-prettier": "^4.2.1", @@ -134,11 +134,11 @@ "eslint-plugin-unused-imports": "^2.0.0", "esno": "^0.16.3", "fast-glob": "^3.2.12", - "happy-dom": "^8.9.0", + "happy-dom": "^9.1.9", "jsdom": "^21.1.1", - "prettier": "^2.8.6", + "prettier": "^2.8.7", "tslib": "^2.5.0", - "typescript": "^5.0.2", + "typescript": "^5.0.3", "vite": "4.2.1", "vitest": "0.29.8" }, diff --git a/packages/preact/preact/src/frame.ts b/packages/preact/preact/src/frame.ts index 1ee419a2..50a0ded8 100644 --- a/packages/preact/preact/src/frame.ts +++ b/packages/preact/preact/src/frame.ts @@ -28,7 +28,7 @@ export class ComponentFrame { } ComponentFrame.#stack.push(component); - frame.#start(description); + frame.#start(); } static isRenderingComponent(component: InternalComponent): boolean { @@ -87,12 +87,12 @@ export class ComponentFrame { this.#subscription = subscribed; } - #start(description: Description | undefined): void { + #start(): void { if (this.#frame) { this.#active = this.#frame.update(); // this.#active = TIMELINE.frame.update(this.#frame); } else { - this.#active = FormulaLifecycle({ description }); + this.#active = FormulaLifecycle(); } } diff --git a/packages/react/react/package.json b/packages/react/react/package.json index cbfea9f7..444d141f 100644 --- a/packages/react/react/package.json +++ b/packages/react/react/package.json @@ -28,10 +28,10 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/collections": "workspace:^", "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/collections": "workspace:^", "@starbeam/modifier": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/resource": "workspace:^", @@ -45,8 +45,8 @@ "devDependencies": { "@domtree/flavors": "workspace:^", "@starbeam-dev/build-support": "workspace:*", - "@types/node": "^18.15.5", - "@types/react": "^18.0.28" + "@types/node": "^18.15.11", + "@types/react": "^18.0.33" }, "peerDependencies": { "react": "^18.2.0", diff --git a/packages/react/react/src/context-provider.ts b/packages/react/react/src/context-provider.ts index 29387888..f60162cf 100644 --- a/packages/react/react/src/context-provider.ts +++ b/packages/react/react/src/context-provider.ts @@ -1,12 +1,7 @@ import { LIFETIME } from "@starbeam/runtime"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; -import type { FunctionComponent } from "react"; -import { - createContext, - createElement, - type PropsWithChildren, - useContext, -} from "react"; +import type { FunctionComponent, PropsWithChildren } from "react"; +import { createContext, createElement, useContext } from "react"; const StarbeamContext = createContext(null as null | ReactApp); diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 4e1d3be9..4c9c625e 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,7 +1,6 @@ import type { browser } from "@domtree/flavors"; -import type { DebugListener } from "@starbeam/debug"; import type { Description, Reactive, Tagged } from "@starbeam/interfaces"; -import { RUNTIME } from "@starbeam/reactive"; +import { RUNTIME, Formula } from "@starbeam/reactive"; import type { IntoResourceBlueprint, Resource } from "@starbeam/resource"; import * as resource from "@starbeam/resource"; import { @@ -13,10 +12,9 @@ import { type Unsubscribe, } from "@starbeam/runtime"; import { service } from "@starbeam/service"; -import { Cell, PolledFormula } from "@starbeam/universal"; +import { Cell } from "@starbeam/universal"; -import { ReactApp } from "./context-provider.js"; -import { missingApp } from "./context-provider.js"; +import { missingApp, ReactApp } from "./context-provider.js"; import { type ElementRef, type ReactElementRef, ref } from "./ref.js"; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -124,6 +122,8 @@ class Refs { } } +type DebugListener = unknown; + export type DebugLifecycle = ( listener: DebugListener, reactive: Tagged @@ -301,7 +301,7 @@ export function internalUseResource( host.on.layout(create); - const formula = PolledFormula(() => { + const formula = Formula(() => { return (resourceCell.current?.current as T | undefined) ?? initial; }); diff --git a/packages/react/react/src/use-reactive.ts b/packages/react/react/src/use-reactive.ts index fc81391e..f9141b64 100644 --- a/packages/react/react/src/use-reactive.ts +++ b/packages/react/react/src/use-reactive.ts @@ -1,11 +1,9 @@ import type { Description, Reactive } from "@starbeam/interfaces"; -import { RUNTIME } from "@starbeam/reactive"; +import { RUNTIME, Formula as Formula, CachedFormula } from "@starbeam/reactive"; import { PUBLIC_TIMELINE } from "@starbeam/runtime"; import { Cell, - Formula, LIFETIME, - PolledFormula, Wrap, } from "@starbeam/universal"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; @@ -38,7 +36,7 @@ export function useReactive( // compute can change, so the `PolledFormula` doesn't close over the original value, but // rather invokes the **current** value (which can change in `on.update`). - const formula = PolledFormula(() => compute(), desc); + const formula = Formula(() => compute(), desc); on.update((newCompute) => { compute = newCompute; @@ -101,7 +99,7 @@ export class MountedReactive { ), }); this.#value = undefined; - this.formula = Formula( + this.formula = CachedFormula( () => this.#cell.current?.current ?? this.#initial, description?.implementation( "formula", diff --git a/packages/react/react/src/use-setup.ts b/packages/react/react/src/use-setup.ts index 29be35f4..566ddcac 100644 --- a/packages/react/react/src/use-setup.ts +++ b/packages/react/react/src/use-setup.ts @@ -1,6 +1,5 @@ import type { Description, Reactive } from "@starbeam/interfaces"; -import { isReactive, RUNTIME } from "@starbeam/reactive"; -import { PolledFormula } from "@starbeam/universal"; +import { isReactive, RUNTIME, Formula } from "@starbeam/reactive"; import { setupFunction, unsafeTrackedElsewhere, @@ -77,7 +76,7 @@ export function useSetup< ReactiveElement.subscribe(element, instance); return { element, instance: { type: "reactive", value: instance } }; } else if (typeof instance === "function") { - const reactive = PolledFormula(() => { + const reactive = Formula(() => { return (instance as (props: unknown) => unknown)(currentProps); }, desc); diff --git a/packages/react/react/tests/use-reactive.spec.ts b/packages/react/react/tests/use-reactive.spec.ts index 8ccaf8ee..f50fb44d 100644 --- a/packages/react/react/tests/use-reactive.spec.ts +++ b/packages/react/react/tests/use-reactive.spec.ts @@ -1,7 +1,8 @@ // @vitest-environment jsdom import { useReactive, useSetup } from "@starbeam/react"; -import { Cell, Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; +import { Cell } from "@starbeam/universal"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; import { describe, expect } from "@starbeam-workspace/test-utils"; import { useState } from "react"; @@ -55,7 +56,7 @@ describe("useReactive", () => { ++testId; const { counter } = useSetup(() => { const cell = Cell(INITIAL_COUNT, `#${testId}`); - return Formula( + return CachedFormula( () => ({ counter: cell.current }), `inner #${testId}` ); @@ -85,7 +86,7 @@ describe("useReactive", () => { const { formula, increment } = useSetup(() => { const cell = Cell(INITIAL_COUNT, `#${nextId}`); return { - formula: Formula( + formula: CachedFormula( () => ({ counter: cell.current }), `inner #${nextId}` ), diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index c00eb084..bc3012ea 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -3,13 +3,8 @@ import reactive from "@starbeam/collections"; import type { Reactive } from "@starbeam/interfaces"; import { use, useProp, useReactive, useSetup } from "@starbeam/react"; -import { intoReactive } from "@starbeam/reactive"; -import { - Cell, - Formula, - Resource, - type ResourceBlueprint, -} from "@starbeam/universal"; +import { CachedFormula, intoReactive } from "@starbeam/reactive"; +import { Cell, Resource, type ResourceBlueprint } from "@starbeam/universal"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; import { beforeEach, describe, expect } from "@starbeam-workspace/test-utils"; @@ -226,7 +221,7 @@ describe("use", () => { const { name, increment } = useSetup(() => { const count = Cell(0, { description: `count` }); - const name = Formula(() => `channel${count.current}`, { + const name = CachedFormula(() => `channel${count.current}`, { description: `channel-name`, }); @@ -307,7 +302,7 @@ describe("use", () => { const { channel, increment } = useSetup(({ use }) => { const count = Cell(0, { description: `count` }); - const name = Formula(() => `channel${count.current}`, { + const name = CachedFormula(() => `channel${count.current}`, { description: `channel-name`, }); diff --git a/packages/universal/collections/src/decorator.ts b/packages/universal/collections/src/decorator.ts index 075143ba..bc9fe3ce 100644 --- a/packages/universal/collections/src/decorator.ts +++ b/packages/universal/collections/src/decorator.ts @@ -1,4 +1,4 @@ -import { Formula } from "@starbeam/universal"; +import { Formula } from "@starbeam/reactive"; import { expected, isPresent, verify } from "@starbeam/verify"; export const cached = ( diff --git a/packages/universal/collections/tests/array.spec.ts b/packages/universal/collections/tests/array.spec.ts index a92280f0..d51d770e 100644 --- a/packages/universal/collections/tests/array.spec.ts +++ b/packages/universal/collections/tests/array.spec.ts @@ -1,5 +1,5 @@ import { reactive } from "@starbeam/collections"; -import { Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; import { describe, expect, test } from "vitest"; import { Invalidation } from "./support.js"; @@ -11,8 +11,8 @@ describe("TrackedArray", () => { const array = reactive.array([]); expect(array.length).toBe(0); - const size = Formula(() => `The array has ${array.length} items`); - const isEmpty = Formula(() => array.length === 0); + const size = CachedFormula(() => `The array has ${array.length} items`); + const isEmpty = CachedFormula(() => array.length === 0); expect(size.current).toBe("The array has 0 items"); expect(isEmpty.current).toBe(true); diff --git a/packages/universal/collections/tests/object.spec.ts b/packages/universal/collections/tests/object.spec.ts index b1dee0d6..87f24c32 100644 --- a/packages/universal/collections/tests/object.spec.ts +++ b/packages/universal/collections/tests/object.spec.ts @@ -1,5 +1,5 @@ import { reactive } from "@starbeam/collections"; -import { Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; import { describe, expect, test } from "vitest"; import { Invalidation } from "./support.js"; @@ -8,9 +8,11 @@ describe("TrackedObject", () => { test("adding and deleting items updates the size", () => { const object = reactive.object>({}); - const size = Formula(() => Object.keys(object).length); - const described = Formula(() => `The object has ${size.current} items`); - const isEmpty = Formula(() => size.current === 0); + const size = CachedFormula(() => Object.keys(object).length); + const described = CachedFormula( + () => `The object has ${size.current} items` + ); + const isEmpty = CachedFormula(() => size.current === 0); expect(size.current).toBe(0); expect(described.current).toBe("The object has 0 items"); diff --git a/packages/universal/collections/tests/set.spec.ts b/packages/universal/collections/tests/set.spec.ts index 07140b28..10103c5e 100644 --- a/packages/universal/collections/tests/set.spec.ts +++ b/packages/universal/collections/tests/set.spec.ts @@ -1,5 +1,5 @@ import { reactive } from "@starbeam/collections"; -import { Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; import { describe, expect, test } from "vitest"; import { Invalidation } from "./support.js"; @@ -9,7 +9,7 @@ describe("TrackedSet", () => { const set = reactive.Set(); expect(set.size).toBe(0); - const size = Formula(() => `The set has ${set.size} items`); + const size = CachedFormula(() => `The set has ${set.size} items`); expect(size.current).toBe("The set has 0 items"); diff --git a/packages/universal/collections/tests/support.ts b/packages/universal/collections/tests/support.ts index 35690860..dcd0f2b6 100644 --- a/packages/universal/collections/tests/support.ts +++ b/packages/universal/collections/tests/support.ts @@ -1,4 +1,5 @@ -import { Formula } from "@starbeam/universal"; +import type { Formula } from "@starbeam/reactive"; +import { CachedFormula } from "@starbeam/reactive"; export class Invalidation { static trace(formula: () => T): Invalidation { @@ -11,7 +12,7 @@ export class Invalidation { #initialized = false; constructor(formula: () => T) { - this.#formula = Formula(() => { + this.#formula = CachedFormula(() => { this.#bumped++; return formula(); }); diff --git a/packages/universal/core-utils/src/array.ts b/packages/universal/core-utils/src/array.ts index cada17b9..5fd60ae5 100644 --- a/packages/universal/core-utils/src/array.ts +++ b/packages/universal/core-utils/src/array.ts @@ -127,19 +127,17 @@ export function getFirst( list: [I, ...unknown[]] | readonly [I, ...unknown[]] ): I; export function getFirst(list: PresentArray): T; -export function getFirst(list: AnyArray): T | undefined; -export function getFirst(list: AnyArray): T | undefined { - return list[FIRST_OFFSET]; +export function getFirst(list: AnyArray | undefined): T | undefined; +export function getFirst(list: AnyArray | undefined): T | undefined { + return list?.[FIRST_OFFSET]; } export function getLast(list: PresentArray): T; -export function getLast(list: T[] | readonly T[]): T | undefined; -export function getLast(list: readonly T[] | T[]): T | undefined { - if (isPresentArray(list)) { - return list[getLastIndex(list)]; - } else { - return undefined; - } +export function getLast(list: T[] | readonly T[] | undefined): T | undefined; +export function getLast( + list: readonly T[] | T[] | undefined +): T | undefined { + return isPresentArray(list) ? list[getLastIndex(list)] : undefined; } export function getLastIndex(list: PresentArray): number; diff --git a/packages/universal/debug/src/description/debug/describe.ts b/packages/universal/debug/src/description/debug/describe.ts index be3aa7ae..5e7c05db 100644 --- a/packages/universal/debug/src/description/debug/describe.ts +++ b/packages/universal/debug/src/description/debug/describe.ts @@ -8,14 +8,15 @@ import type { ReactiveType, Tagged, } from "@starbeam/interfaces"; +import { UNKNOWN_REACTIVE_VALUE } from "@starbeam/reactive"; import { getID } from "@starbeam/shared"; import { getDescription } from "@starbeam/tags"; export type FullName = Flat | [Flat, ...ChildType[]]; export function describeTagged(tagged: Tagged): string { - const description = getDescription(tagged)?.details; - return description ? describe(description) : `{unknown reactive value}`; + const description = getDescription(tagged); + return description ? describe(description) : UNKNOWN_REACTIVE_VALUE; } export function describe(description: DescriptionDetails): string { diff --git a/packages/universal/debug/src/description/debug/description.ts b/packages/universal/debug/src/description/debug/description.ts index f437e12b..a7abc9de 100644 --- a/packages/universal/debug/src/description/debug/description.ts +++ b/packages/universal/debug/src/description/debug/description.ts @@ -2,25 +2,33 @@ import { getFirst, isObject } from "@starbeam/core-utils"; import type { Api, CallStack, + Description as IDescription, + DescriptionDetails, DescriptionRuntime, + Nesting, ReactiveId, + ReactiveType, + StackFrame, } from "@starbeam/interfaces"; -import type * as interfaces from "@starbeam/interfaces"; import { RUNTIME } from "@starbeam/reactive"; import { getID } from "@starbeam/shared"; -export class Description implements interfaces.Description { - readonly #details: interfaces.DescriptionDetails; +export class Description implements IDescription { + readonly #details: DescriptionDetails; - constructor(desc: interfaces.DescriptionDetails) { + constructor(desc: DescriptionDetails) { this.#details = desc; } - get details(): interfaces.DescriptionDetails { - return this.#details; + get api(): Api | undefined { + return this.#details.api; } - get type(): interfaces.ReactiveType { + get nesting(): Nesting | undefined { + return this.#details.nesting; + } + + get type(): ReactiveType { return this.#details.type; } @@ -28,7 +36,7 @@ export class Description implements interfaces.Description { return this.#details.caller; } - get frame(): interfaces.StackFrame | undefined { + get frame(): StackFrame | undefined { return getFirst(this.caller?.frames ?? []); } @@ -40,7 +48,7 @@ export class Description implements interfaces.Description { return this.#details.specified === undefined; } - index(index: number, caller?: CallStack | undefined): interfaces.Description { + index(index: number, caller?: CallStack | undefined): IDescription { return new Description({ type: "collection:item", id: this.#extendId(index), @@ -49,10 +57,7 @@ export class Description implements interfaces.Description { }); } - property( - name: string, - caller?: CallStack | undefined - ): interfaces.Description { + property(name: string, caller?: CallStack | undefined): IDescription { return new Description({ type: "collection:item", id: this.#extendId(name), @@ -64,7 +69,7 @@ export class Description implements interfaces.Description { key( key: { name: string; key: unknown } | string | number, caller?: CallStack | undefined - ): interfaces.Description { + ): IDescription { const value: { name: string; key: unknown } = isObject(key) ? { name: key.name, key: key.key } : { name: String(key), key }; @@ -78,11 +83,11 @@ export class Description implements interfaces.Description { } detail( - type: interfaces.ReactiveType, + type: ReactiveType, name: string, args: string[] | CallStack = [], caller?: CallStack | undefined - ): interfaces.Description { + ): IDescription { const info = Array.isArray(args) ? { args, caller } : { args: [], caller: args }; @@ -100,11 +105,11 @@ export class Description implements interfaces.Description { } implementation( - type: interfaces.ReactiveType, + type: ReactiveType, name: string, reason: string, caller?: CallStack | undefined - ): interfaces.Description { + ): IDescription { return new Description({ type, id: this.#extendId(name), @@ -125,21 +130,23 @@ export class Description implements interfaces.Description { const DESC_FRAME = 1; export const Desc = (( - type: interfaces.ReactiveType, - specified: string | interfaces.Description | undefined, - api: string | Api | undefined -): interfaces.Description => { + type: ReactiveType, + specified?: string | IDescription | undefined, + api?: string | Api | undefined +): IDescription => { if (isObject(specified)) return specified; const caller = RUNTIME.callerStack?.(DESC_FRAME); - api = api ?? caller?.frames[0].action; + api = api ?? getFirst(caller?.frames)?.action; const id = getID(); - return new Description({ + const desc = new Description({ type, id, api: typeof api === "string" ? { type: "simple", name: api, caller } : api, specified, caller, }); + console.log({ desc: { ...desc } }); + return desc; }) satisfies DescriptionRuntime; diff --git a/packages/universal/debug/src/description/interface.ts b/packages/universal/debug/src/description/interface.ts deleted file mode 100644 index 153484d8..00000000 --- a/packages/universal/debug/src/description/interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Description, ReactiveType } from "@starbeam/interfaces"; - -export type DescriptionRuntime = ( - type: ReactiveType, - specified: string | undefined, - create?: (desc: Description) => Description -) => Description | undefined; diff --git a/packages/universal/debug/src/description/prod.ts b/packages/universal/debug/src/description/prod.ts index 34b97da3..7aed9aaa 100644 --- a/packages/universal/debug/src/description/prod.ts +++ b/packages/universal/debug/src/description/prod.ts @@ -1,3 +1,3 @@ -import type { DescriptionRuntime } from "./interface.js"; +import type { DescriptionRuntime } from "@starbeam/interfaces"; export default (() => undefined) satisfies DescriptionRuntime; diff --git a/packages/universal/interfaces/src/debug/debug-runtime.ts b/packages/universal/interfaces/src/debug/debug-runtime.ts index f90216c1..e93f5a88 100644 --- a/packages/universal/interfaces/src/debug/debug-runtime.ts +++ b/packages/universal/interfaces/src/debug/debug-runtime.ts @@ -18,5 +18,6 @@ export interface DebugRuntime { barrier: (tag: Tag, stack: CallStack | undefined) => void | never ) => void; readonly callerStack: CallerStackFn; + readonly desc: DescriptionRuntime; } diff --git a/packages/universal/interfaces/src/debug/description.ts b/packages/universal/interfaces/src/debug/description.ts index d258c955..8c4b722a 100644 --- a/packages/universal/interfaces/src/debug/description.ts +++ b/packages/universal/interfaces/src/debug/description.ts @@ -17,13 +17,23 @@ export type DescriptionRuntime = ( api?: Api | string | undefined ) => Description | undefined; -export interface Description { +export interface DescriptionDetails { readonly id: ReactiveId; - readonly details: DescriptionDetails; readonly type: ReactiveType; + readonly api?: Api | undefined; readonly caller: CallStack | undefined; + readonly nesting?: Nesting | undefined; + /** + * The user-specified description, if specified. + */ + readonly specified?: string | undefined; +} + +export interface Description extends DescriptionDetails { readonly frame: StackFrame | undefined; readonly isAnonymous: boolean; + readonly api: Api | undefined; + readonly nesting: Nesting | undefined; index: (index: number, caller?: CallStack | undefined) => Description; property: (name: string, caller?: CallStack | undefined) => Description; @@ -45,18 +55,6 @@ export interface Description { ) => Description; } -export interface DescriptionDetails { - readonly id: ReactiveId; - readonly type: ReactiveType; - readonly api?: Api | undefined; - readonly caller: CallStack | undefined; - readonly nesting?: Nesting | undefined; - /** - * The user-specified description, if specified. - */ - readonly specified?: string | undefined; -} - export type Api = FunctionApi | MethodApi | SimpleFunctionApi; export interface SomeApi { diff --git a/packages/universal/interfaces/src/protocol.ts b/packages/universal/interfaces/src/protocol.ts index adba4119..38812d8a 100644 --- a/packages/universal/interfaces/src/protocol.ts +++ b/packages/universal/interfaces/src/protocol.ts @@ -155,7 +155,11 @@ export interface TaggedReactive export interface ReactiveCell extends ReactiveValue { current: T; - set: (value: T, caller?: CallStack) => void; + /** + * Set the value of the cell. Returns true if the value was changed, false if + * the current value was equivalent to the new value. + */ + set: (value: T, caller?: CallStack) => boolean; update: (fn: (value: T) => T, caller?: CallStack) => void; freeze: () => void; } diff --git a/packages/universal/modifier/src/modifier.ts b/packages/universal/modifier/src/modifier.ts index b46f35c4..e31eac52 100644 --- a/packages/universal/modifier/src/modifier.ts +++ b/packages/universal/modifier/src/modifier.ts @@ -2,7 +2,7 @@ import type { anydom } from "@domtree/flavors"; import type { Description, Tagged } from "@starbeam/interfaces"; import { RUNTIME } from "@starbeam/reactive"; import { TAG, UNINITIALIZED } from "@starbeam/shared"; -import { DelegateTag, getTag } from "@starbeam/tags"; +import { createDelegateTag, getTag } from "@starbeam/tags"; import { Cell } from "@starbeam/universal"; import { expected, isPresent, verified, verify } from "@starbeam/verify"; @@ -23,11 +23,11 @@ const REFS = new WeakMap>(); export function ElementPlaceholder( type: ElementType, - description: Description + description: Description | undefined ): ElementPlaceholder { const ref = Object.create(null) as object; const elementCell = Cell(UNINITIALIZED, { - description: description.implementation( + description: description?.implementation( "cell", "element", "ref placeholder" @@ -37,14 +37,14 @@ export function ElementPlaceholder( REFS.set(ref, elementCell); return { - [TAG]: DelegateTag.create(description, [getTag(elementCell)]), + [TAG]: createDelegateTag(description, [getTag(elementCell)]), initialize(value: anydom.Element): void { const element = verified(REFS.get(ref), isPresent); verify( value, (anyElement): anyElement is E => anyElement instanceof type, - expected(`A ref (${RUNTIME.debug?.describe(description) ?? "unknown"})`) + expected(`A ref (${RUNTIME.describe(description)})`) .toBe(`initialized with an instance of ${type.name}`) .butGot(() => `an instance of ${value.constructor.name}`) ); diff --git a/packages/universal/reactive/index.ts b/packages/universal/reactive/index.ts index 96cd5e9c..e1ddcf98 100644 --- a/packages/universal/reactive/index.ts +++ b/packages/universal/reactive/index.ts @@ -10,7 +10,11 @@ export { export { Marker } from "./src/primitives/marker.js"; export { Static } from "./src/primitives/static.js"; export { type FormulaFn, isFormulaFn } from "./src/primitives/utils.js"; -export { defineRuntime, RUNTIME } from "./src/runtime.js"; +export { + defineRuntime, + RUNTIME, + UNKNOWN_REACTIVE_VALUE, +} from "./src/runtime.js"; export { intoReactive, isReactive, diff --git a/packages/universal/reactive/src/primitives/cell.ts b/packages/universal/reactive/src/primitives/cell.ts index a91d7e7c..818f77e1 100644 --- a/packages/universal/reactive/src/primitives/cell.ts +++ b/packages/universal/reactive/src/primitives/cell.ts @@ -5,7 +5,7 @@ import { createCellTag } from "@starbeam/tags"; import { RUNTIME } from "../runtime.js"; import { isDescriptionOption, type PrimitiveOptions } from "./utils.js"; -export type Cell = ReactiveCell; +export type Cell = ReactiveCell; export function Cell( value: T, diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index 8e94cb80..ead0523e 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -2,7 +2,7 @@ import type { AutotrackingRuntime, CallerStackFn, DebugRuntime, - DescriptionRuntime, + DescriptionDetails, Runtime, SubscriptionRuntime, Tag, @@ -28,9 +28,14 @@ function getRuntime(): Runtime { return CONTEXT.runtime as Runtime; } +export const UNKNOWN_REACTIVE_VALUE = "{unknown reactive value}"; + +type DescFn = + typeof import("../../debug/src/description/debug/description.js")["Desc"]; + class RuntimeImpl implements Runtime { - get Desc(): DescriptionRuntime | undefined { - return getRuntime().debug?.desc ?? undefined; + get Desc(): DescFn | undefined { + return (getRuntime().debug?.desc as DescFn) ?? undefined; } get callerStack(): CallerStackFn | undefined { @@ -49,6 +54,16 @@ class RuntimeImpl implements Runtime { return getRuntime().debug; } + describe(description: DescriptionDetails | undefined): string { + if (description) { + return ( + getRuntime().debug?.describe?.(description) ?? UNKNOWN_REACTIVE_VALUE + ); + } else { + return UNKNOWN_REACTIVE_VALUE; + } + } + evaluate(compute: () => T): { value: T; tags: Set } { const done = this.autotracking.start(); const value = compute(); diff --git a/packages/universal/resource/tests/package.json b/packages/universal/resource/tests/package.json index 3b470603..e980be19 100644 --- a/packages/universal/resource/tests/package.json +++ b/packages/universal/resource/tests/package.json @@ -9,13 +9,13 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/collections": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/collections": "workspace:^", "@starbeam/reactive": "workspace:^", - "@starbeam-workspace/test-utils": "workspace:^", "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", - "@starbeam/shared": "workspace:^" + "@starbeam/shared": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^" } } diff --git a/packages/universal/runtime/tests/description.spec.ts b/packages/universal/runtime/tests/description.spec.ts new file mode 100644 index 00000000..d7ba5aaf --- /dev/null +++ b/packages/universal/runtime/tests/description.spec.ts @@ -0,0 +1,20 @@ +import { RUNTIME } from "@starbeam/reactive"; +import { expect, test } from "@starbeam-workspace/test-utils"; + +test("inferred api", () => { + expect(SomeAPI()?.api).toMatchObject({ + type: "simple", + name: "SomeAPI", + }); + + expect(ArrowFn()?.api).toMatchObject({ + type: "simple", + name: "ArrowFn", + }); +}); + +function SomeAPI() { + return RUNTIME.Desc?.("cell"); +} + +const ArrowFn = () => RUNTIME.Desc?.("cell"); diff --git a/packages/universal/runtime/tests/package.json b/packages/universal/runtime/tests/package.json index 81ede178..1d3a603e 100644 --- a/packages/universal/runtime/tests/package.json +++ b/packages/universal/runtime/tests/package.json @@ -13,6 +13,7 @@ "@starbeam/interfaces": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/runtime": "workspace:^", - "@starbeam/shared": "workspace:^" + "@starbeam/shared": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^" } } diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 3a848b2a..95e72725 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -6,14 +6,7 @@ export { Variants, type VariantType, } from "./src/reactive-core/variants.js"; -export { - Cell, - type Equality, - // FIXME: Migrate these to their ultimate names - CachedFormula as Formula, - Formula as PolledFormula, - Static, -} from "@starbeam/reactive"; +export { Cell, type Equality, Static } from "@starbeam/reactive"; export { Wrap } from "@starbeam/reactive/src/primitives/delegate.js"; export { Resource, diff --git a/packages/universal/universal/tests/formula.spec.ts b/packages/universal/universal/tests/formula.spec.ts index cc696f53..a10de929 100644 --- a/packages/universal/universal/tests/formula.spec.ts +++ b/packages/universal/universal/tests/formula.spec.ts @@ -1,5 +1,6 @@ import { cached, reactive } from "@starbeam/collections"; -import { Cell, Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; +import { Cell } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; describe("A reactive formula", () => { @@ -7,7 +8,7 @@ describe("A reactive formula", () => { const name = Cell("@tomdale"); const location = Cell("New York"); - const card = Formula(() => `${name.current} (${location.current})`); + const card = CachedFormula(() => `${name.current} (${location.current})`); expect(card()).toBe("@tomdale (New York)"); @@ -20,7 +21,7 @@ describe("A reactive formula", () => { const name = Cell("@tomdale", { description: "name" }); const location = Cell("New York", { description: "location" }); - const card = Formula( + const card = CachedFormula( () => ({ name: name.current, location: location.current, @@ -67,7 +68,7 @@ describe("A reactive formula", () => { const name = Cell("@tomdale"); const location = Cell("New York"); - const card = Formula(() => ({ + const card = CachedFormula(() => ({ name: name.current, location: location.current, })); @@ -103,7 +104,7 @@ describe("A reactive formula", () => { { equals: (a, b) => a.name === b.name && a.location === b.location } ); - const card = Formula(() => ({ + const card = CachedFormula(() => ({ name: person.current.name, location: person.current.location, })); @@ -151,8 +152,8 @@ describe("A reactive formula", () => { const location = Cell("New York"); const organization = Cell("LinkedIn"); - const card = Formula(() => `${name.current} (${location.current})`); - const complete = Formula( + const card = CachedFormula(() => `${name.current} (${location.current})`); + const complete = CachedFormula( () => `${card.current} at ${organization.current}` ); @@ -205,7 +206,7 @@ test("Formula using cells", () => { const person = new Person("Tom", "USA"); let counter = 0; - const formatted = Formula(() => { + const formatted = CachedFormula(() => { counter++; return person.formatted(false); }); @@ -244,7 +245,7 @@ test("Formula using the @reactive decorator", () => { const person = new Person("Tom", "USA"); let counter = 0; - const formatted = Formula(() => { + const formatted = CachedFormula(() => { counter++; return person.formatted(false); }); diff --git a/packages/universal/universal/tests/package.json b/packages/universal/universal/tests/package.json index 88144607..84932dbb 100644 --- a/packages/universal/universal/tests/package.json +++ b/packages/universal/universal/tests/package.json @@ -9,8 +9,8 @@ "test:types": "tsc -b" }, "dependencies": { - "@starbeam/debug": "workspace:^", "@starbeam/collections": "workspace:^", + "@starbeam/debug": "workspace:^", "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" diff --git a/packages/universal/universal/tests/polled-formula.spec.ts b/packages/universal/universal/tests/polled-formula.spec.ts index ad0101c3..62b1a5c1 100644 --- a/packages/universal/universal/tests/polled-formula.spec.ts +++ b/packages/universal/universal/tests/polled-formula.spec.ts @@ -1,5 +1,6 @@ import { cached, reactive } from "@starbeam/collections"; -import { Cell, PolledFormula } from "@starbeam/universal"; +import { Formula } from "@starbeam/reactive"; +import { Cell } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; describe("A polled reactive formula", () => { @@ -7,7 +8,7 @@ describe("A polled reactive formula", () => { const name = Cell("@tomdale"); const location = Cell("New York"); - const card = PolledFormula(() => `${name.current} (${location.current})`); + const card = Formula(() => `${name.current} (${location.current})`); expect(card.current).toBe("@tomdale (New York)"); @@ -20,7 +21,7 @@ describe("A polled reactive formula", () => { const name = Cell("@tomdale"); const location = Cell("New York"); - const card = PolledFormula(() => ({ + const card = Formula(() => ({ name: name.current, location: location.current, })); @@ -64,7 +65,7 @@ describe("A polled reactive formula", () => { const name = Cell("@tomdale"); const location = Cell("New York"); - const card = PolledFormula(() => ({ + const card = Formula(() => ({ name: name.current, location: location.current, })); @@ -106,7 +107,7 @@ describe("A polled reactive formula", () => { { equals: (a, b) => a.name === b.name && a.location === b.location } ); - const card = PolledFormula(() => ({ + const card = Formula(() => ({ name: person.current.name, location: person.current.location, })); @@ -156,8 +157,8 @@ describe("A polled reactive formula", () => { const location = Cell("New York"); const organization = Cell("LinkedIn"); - const card = PolledFormula(() => `${name.current} (${location.current})`); - const complete = PolledFormula( + const card = Formula(() => `${name.current} (${location.current})`); + const complete = Formula( () => `${card.current} at ${organization.current}` ); @@ -195,7 +196,7 @@ test("Formula", () => { const person = new Person("Tom", "USA"); let counter = 0; - const formatted = PolledFormula(() => { + const formatted = Formula(() => { counter++; return person.formatted(false); }); diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 10102039..2847bd40 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -1,6 +1,7 @@ -import { RUNTIME } from "@starbeam/reactive"; +import type { Formula } from "@starbeam/reactive"; +import { CachedFormula, RUNTIME } from "@starbeam/reactive"; import { PUBLIC_TIMELINE, type Tagged } from "@starbeam/runtime"; -import { Formula, Variants } from "@starbeam/universal"; +import { Variants } from "@starbeam/universal"; import { describe, expect, test } from "vitest"; interface Bool { @@ -25,7 +26,7 @@ describe("Variants", () => { const Bool = Variants(); const bool = Bool.true(); - const type = Formula(() => bool.current.type); + const type = CachedFormula(() => bool.current.type); expect(type.current).toBe("true"); const typeStable = Stability(type); @@ -73,7 +74,7 @@ describe("Variants", () => { const Lifecycle = Variants>("Lifecycle"); const lifecycle = Lifecycle.idle(); - const advance = Formula( + const advance = CachedFormula( () => { // this is testing that only a transition from idle or to idle invalidates this formula, and // not transitions between other variants. This formula will invalidate if the variant returns @@ -85,7 +86,7 @@ describe("Variants", () => { { description: "advance" } ); - const render = Formula( + const render = CachedFormula( (): number | Error | "idle" | "loading" => { advance(); @@ -104,7 +105,7 @@ describe("Variants", () => { { description: "render" } ); - const value = Formula( + const value = CachedFormula( () => { return lifecycle.match({ loaded: (v) => v, @@ -179,7 +180,7 @@ describe("Variants", () => { const Lifecycle = Variants>("Lifecycle"); const lifecycle = Lifecycle.idle(); - const isResolved = Formula(() => { + const isResolved = CachedFormula(() => { return lifecycle.is("loaded", "error"); }); @@ -248,7 +249,7 @@ function Instrument( }) => T | Formula { let status: "initial" | "initialized" | "changed" | "stable" = "initial"; - const formula = Formula(() => { + const formula = CachedFormula(() => { if (status === "initial") { status = "initialized"; } else { diff --git a/packages/x/devtool/package.json b/packages/x/devtool/package.json index 0e70ecb6..c49a0936 100644 --- a/packages/x/devtool/package.json +++ b/packages/x/devtool/package.json @@ -32,10 +32,10 @@ "@starbeam/core-utils": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", - "@starbeam/tags": "workspace:^", "@starbeam/runtime": "workspace:^", + "@starbeam/tags": "workspace:^", "@starbeam/verify": "workspace:^", - "preact": "^10.13.1" + "preact": "^10.13.2" }, "devDependencies": { "@starbeam-dev/build-support": "workspace:*" diff --git a/packages/x/store/tests/aggregating.spec.ts b/packages/x/store/tests/aggregating.spec.ts index 2238dc6c..2840614b 100644 --- a/packages/x/store/tests/aggregating.spec.ts +++ b/packages/x/store/tests/aggregating.spec.ts @@ -1,4 +1,4 @@ -import { Cell, Formula } from "@starbeam/universal"; +import { CachedFormula, Cell } from "@starbeam/reactive"; import { isPresent, verified } from "@starbeam/verify"; import { type Aggregator, Average, Sum, Table } from "@starbeamx/store"; import { describe, expect, test } from "vitest"; @@ -86,7 +86,7 @@ describe("aggregating tables", () => { people.append(...data); - const averageAge = Formula(() => { + const averageAge = CachedFormula(() => { const average = people.aggregateBy({ age: Average, }); @@ -94,7 +94,7 @@ describe("aggregating tables", () => { return average.row.age; }); - const totalVisits = Formula(() => { + const totalVisits = CachedFormula(() => { const total = people.aggregateBy({ visits: Sum, }); @@ -160,7 +160,7 @@ describe("aggregating tables", () => { const aggregate = Cell(Sum as Aggregator); - const activeVisits = Formula(() => { + const activeVisits = CachedFormula(() => { const byStatus = people.groupBy((row) => ({ bucket: row.status })); const active = verified(byStatus.groups.get("active"), isPresent); diff --git a/packages/x/store/tests/grouping.spec.ts b/packages/x/store/tests/grouping.spec.ts index 4166d262..804fbdc3 100644 --- a/packages/x/store/tests/grouping.spec.ts +++ b/packages/x/store/tests/grouping.spec.ts @@ -1,4 +1,4 @@ -import { Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; import { isPresent, verified } from "@starbeam/verify"; import { Table } from "@starbeamx/store"; import { describe, expect, test } from "vitest"; @@ -177,7 +177,7 @@ describe("grouping tables", () => { people.append(...data); // group by age decade - const byAgeDecade = Formula(() => { + const byAgeDecade = CachedFormula(() => { return people.groupBy((row) => { const decade = Math.floor(row.age / 10); return { bucket: decade, as: `${decade}0s` }; diff --git a/packages/x/store/tests/query.spec.ts b/packages/x/store/tests/query.spec.ts index 618119ce..965d3f70 100644 --- a/packages/x/store/tests/query.spec.ts +++ b/packages/x/store/tests/query.spec.ts @@ -1,4 +1,4 @@ -import { Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; import { Query, Table } from "@starbeamx/store"; import { describe, expect, test } from "vitest"; @@ -104,25 +104,27 @@ describe("queries", () => { .filter(({ name }) => name === "John") .and(({ location }) => location === "Berlin"); - const johnInBerlin = Formula(() => cards(johnInBerlinQuery.rows)); + const johnInBerlin = CachedFormula(() => cards(johnInBerlinQuery.rows)); const berlinQuery = Query.for(people).filter( ({ location }) => location === "Berlin" ); - const berliners = Formula(() => cards(berlinQuery.rows)); + const berliners = CachedFormula(() => cards(berlinQuery.rows)); const jNamesQuery = Query.for(people).filter(({ name }) => name.startsWith("J") ); - const jNames = Formula(() => cards(jNamesQuery.rows)); + const jNames = CachedFormula(() => cards(jNamesQuery.rows)); const johnOrBerlinQuery = Query.for(people) .filter(({ name }) => name === "John") .or(({ location }) => location === "Berlin"); - const johnsAndBerliners = Formula(() => cards(johnOrBerlinQuery.rows)); + const johnsAndBerliners = CachedFormula(() => + cards(johnOrBerlinQuery.rows) + ); expect(johnInBerlin.current).toEqual("

    John (in Berlin)

    "); expect(berliners.current).toEqual("

    John (in Berlin)

    "); @@ -180,25 +182,27 @@ describe("queries", () => { .filter(({ name }) => name === "John") .and(({ location }) => location === "Berlin"); - const johnInBerlin = Formula(() => cards(johnInBerlinQuery.rows)); + const johnInBerlin = CachedFormula(() => cards(johnInBerlinQuery.rows)); const berlinQuery = Query.for(people).filter( ({ location }) => location === "Berlin" ); - const berliners = Formula(() => cards(berlinQuery.rows)); + const berliners = CachedFormula(() => cards(berlinQuery.rows)); const jNamesQuery = Query.for(people).filter(({ name }) => name.startsWith("J") ); - const jNames = Formula(() => cards(jNamesQuery.rows)); + const jNames = CachedFormula(() => cards(jNamesQuery.rows)); const johnOrBerlinQuery = Query.for(people) .filter(({ name }) => name === "John") .or(({ location }) => location === "Berlin"); - const johnsAndBerliners = Formula(() => cards(johnOrBerlinQuery.rows)); + const johnsAndBerliners = CachedFormula(() => + cards(johnOrBerlinQuery.rows) + ); expect(johnInBerlin.current).toEqual("

    John (in Berlin)

    "); expect(berliners.current).toEqual("

    John (in Berlin)

    "); diff --git a/packages/x/store/tests/table.spec.ts b/packages/x/store/tests/table.spec.ts index 04b8f7af..60864058 100644 --- a/packages/x/store/tests/table.spec.ts +++ b/packages/x/store/tests/table.spec.ts @@ -1,4 +1,4 @@ -import { Formula } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; import { Table } from "@starbeamx/store"; import { describe, expect, test } from "vitest"; @@ -47,7 +47,9 @@ describe("tables", () => { test("a table's rows can be enumerated", () => { const people = Table.create({ columns: ["name", "location"] }); - const list = Formula(() => people.rows.map(({ name }) => name).join(", ")); + const list = CachedFormula(() => + people.rows.map(({ name }) => name).join(", ") + ); people.append({ name: "John", location: "Berlin" }); people.append({ name: "Jane", location: "London" }); diff --git a/packages/x/vanilla/package.json b/packages/x/vanilla/package.json index bfdafbbd..c223fbef 100644 --- a/packages/x/vanilla/package.json +++ b/packages/x/vanilla/package.json @@ -28,6 +28,7 @@ "dependencies": { "@starbeam/debug": "workspace:^", "@starbeam/interfaces": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^" }, diff --git a/packages/x/vanilla/src/dom.ts b/packages/x/vanilla/src/dom.ts index 6756241a..84d42f7f 100644 --- a/packages/x/vanilla/src/dom.ts +++ b/packages/x/vanilla/src/dom.ts @@ -1,6 +1,6 @@ import type { Description, Reactive } from "@starbeam/interfaces"; -import { RUNTIME } from "@starbeam/runtime"; -import { Formula, LIFETIME } from "@starbeam/universal"; +import { CachedFormula } from "@starbeam/reactive"; +import { LIFETIME, RUNTIME } from "@starbeam/runtime"; import { Cursor } from "./cursor.js"; @@ -27,7 +27,7 @@ function Render( create({ owner }) { const { cleanup, update } = create({ into, owner }); - const formula = Formula(update, description); + const formula = CachedFormula(update, description); LIFETIME.on.cleanup(owner, cleanup); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f16667be..9341500e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,14 +3,14 @@ lockfileVersion: '6.0' overrides: '@rollup/plugin-commonjs': ^24.0.0 '@rollup/plugin-node-resolve': ^15.0.1 - '@types/eslint': ^8.21.3 - '@types/node': 18.15.5 - '@typescript-eslint/eslint-plugin': ^5.56.0 - '@typescript-eslint/parser': ^5.56.0 - eslint: ^8.36.0 + '@types/eslint': ^8.37.0 + '@types/node': 18.15.11 + '@typescript-eslint/eslint-plugin': ^5.57.1 + '@typescript-eslint/parser': ^5.57.1 + eslint: ^8.37.0 preact: ^10.11.3 rollup: ^3.9.1 - typescript: ^5.0.2 + typescript: ^5.0.3 vite: 4.2.1 vite-plugin-fonts: 0.7.0 vue: ^3.2.39 @@ -25,7 +25,7 @@ importers: devDependencies: '@babel/eslint-parser': specifier: ^7.21.3 - version: 7.21.3(@babel/core@7.21.3)(eslint@8.36.0) + version: 7.21.3(@babel/core@7.21.3)(eslint@8.37.0) '@babel/plugin-proposal-decorators': specifier: ^7.21.0 version: 7.21.0(@babel/core@7.21.3) @@ -33,17 +33,17 @@ importers: specifier: ^7.8.3 version: 7.8.3(@babel/core@7.21.3) '@babel/plugin-transform-runtime': - specifier: ^7.21.0 - version: 7.21.0(@babel/core@7.21.3) + specifier: ^7.21.4 + version: 7.21.4(@babel/core@7.21.3) '@babel/preset-env': - specifier: ^7.20.2 - version: 7.20.2(@babel/core@7.21.3) + specifier: ^7.21.4 + version: 7.21.4(@babel/core@7.21.3) '@babel/preset-react': specifier: ^7.18.6 version: 7.18.6(@babel/core@7.21.3) '@babel/preset-typescript': - specifier: ^7.21.0 - version: 7.21.0(@babel/core@7.21.3) + specifier: ^7.21.4 + version: 7.21.4(@babel/core@7.21.3) '@babel/runtime': specifier: ^7.21.0 version: 7.21.0 @@ -63,47 +63,47 @@ importers: specifier: workspace:^1.0.0 version: link:workspace/eslint '@types/eslint': - specifier: ^8.21.3 - version: 8.21.3 + specifier: ^8.37.0 + version: 8.37.0 '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 '@typescript-eslint/eslint-plugin': - specifier: ^5.56.0 - version: 5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2) + specifier: ^5.57.1 + version: 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3) '@typescript-eslint/parser': - specifier: ^5.56.0 - version: 5.56.0(eslint@8.36.0)(typescript@5.0.2) + specifier: ^5.57.1 + version: 5.57.1(eslint@8.37.0)(typescript@5.0.3) '@vitest/ui': specifier: ^0.29.8 version: 0.29.8 eslint: - specifier: ^8.36.0 - version: 8.36.0 + specifier: ^8.37.0 + version: 8.37.0 eslint-config-airbnb: specifier: ^19.0.4 - version: 19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.36.0) + version: 19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.37.0) eslint-config-prettier: specifier: ^8.8.0 - version: 8.8.0(eslint@8.36.0) + version: 8.8.0(eslint@8.37.0) eslint-import-resolver-typescript: - specifier: ^3.5.3 - version: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0) + specifier: ^3.5.5 + version: 3.5.5(@typescript-eslint/parser@5.57.1)(eslint-plugin-import@2.27.5)(eslint@8.37.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + version: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) eslint-plugin-jsonc: specifier: ^2.7.0 - version: 2.7.0(eslint@8.36.0) + version: 2.7.0(eslint@8.37.0) eslint-plugin-prettier: specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.6) + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.37.0)(prettier@2.8.7) eslint-plugin-simple-import-sort: specifier: ^10.0.0 - version: 10.0.0(eslint@8.36.0) + version: 10.0.0(eslint@8.37.0) eslint-plugin-unused-imports: specifier: ^2.0.0 - version: 2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0) + version: 2.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint@8.37.0) esno: specifier: ^0.16.3 version: 0.16.3 @@ -111,26 +111,26 @@ importers: specifier: ^3.2.12 version: 3.2.12 happy-dom: - specifier: ^8.9.0 - version: 8.9.0 + specifier: ^9.1.9 + version: 9.1.9 jsdom: specifier: ^21.1.1 version: 21.1.1 prettier: - specifier: ^2.8.6 - version: 2.8.6 + specifier: ^2.8.7 + version: 2.8.7 tslib: specifier: ^2.5.0 version: 2.5.0 typescript: - specifier: ^5.0.2 - version: 5.0.2 + specifier: ^5.0.3 + version: 5.0.3 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vitest: specifier: 0.29.8 - version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.8(@vitest/ui@0.29.8)(happy-dom@9.1.9)(jsdom@21.1.1) '@types/@rollup/plugin-commonjs': dependencies: @@ -147,8 +147,8 @@ importers: '@types/ansicolor': devDependencies: '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 '@types/rollup-plugin-polyfill-node': dependencies: @@ -159,14 +159,14 @@ importers: '@types/shell-escape-tag': devDependencies: '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 '@types/shell-split': devDependencies: '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 demos/preact: dependencies: @@ -194,13 +194,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) demos/preact-hello-world: dependencies: @@ -231,13 +231,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) demos/react: dependencies: @@ -271,13 +271,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) demos/react-jsnation: dependencies: @@ -297,24 +297,24 @@ importers: specifier: 3.0.0 version: 3.0.0 react: - specifier: ^18.1.0 + specifier: ^18.2.0 version: 18.2.0 react-dom: - specifier: ^18.1.0 + specifier: ^18.2.0 version: 18.2.0(react@18.2.0) devDependencies: '@types/react': - specifier: ^18.0.26 - version: 18.0.26 + specifier: ^18.0.33 + version: 18.0.33 '@types/react-dom': - specifier: ^18.0.10 - version: 18.0.10 + specifier: ^18.0.11 + version: 18.0.11 '@vitest/ui': specifier: '*' version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) @@ -394,13 +394,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) demos/react-query: dependencies: @@ -449,13 +449,13 @@ importers: version: 5.3.6(react-dom@18.2.0)(react-is@17.0.2)(react@18.2.0) vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) demos/react-stock-ticker: dependencies: @@ -495,13 +495,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) demos/react-store: dependencies: @@ -541,13 +541,13 @@ importers: version: 0.29.7 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1) packages/preact/preact: dependencies: @@ -811,11 +811,11 @@ importers: specifier: workspace:* version: link:../../../workspace/build '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 '@types/react': - specifier: ^18.0.28 - version: 18.0.28 + specifier: ^18.0.33 + version: 18.0.33 packages/react/react/tests: dependencies: @@ -848,7 +848,7 @@ importers: version: 18.2.0 vitest: specifier: '*' - version: 0.29.7(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1) + version: 0.29.7(@vitest/ui@0.29.8)(happy-dom@9.1.9)(jsdom@21.1.1) packages/react/test-utils: dependencies: @@ -1030,8 +1030,8 @@ importers: specifier: workspace:^ version: link:../../../@types/ansicolor '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 packages/universal/debug/tests: dependencies: @@ -1201,6 +1201,9 @@ importers: packages/universal/runtime/tests: dependencies: + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:../../debug @@ -1422,7 +1425,7 @@ importers: version: 10.11.3 vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-mpa: specifier: ^1.1.3 version: 1.1.4 @@ -1469,6 +1472,9 @@ importers: '@starbeam/interfaces': specifier: workspace:^ version: link:../../universal/interfaces + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../universal/reactive '@starbeam/runtime': specifier: workspace:^ version: link:../../universal/runtime @@ -1571,29 +1577,29 @@ importers: specifier: workspace:^ version: link:../../@types/@rollup/plugin-node-resolve '@typescript-eslint/parser': - specifier: ^5.56.0 - version: 5.56.0(eslint@8.36.0)(typescript@5.0.2) + specifier: ^5.57.1 + version: 5.57.1(eslint@8.37.0)(typescript@5.0.3) eslint: - specifier: ^8.36.0 - version: 8.36.0 + specifier: ^8.37.0 + version: 8.37.0 eslint-config-prettier: specifier: ^8.8.0 - version: 8.8.0(eslint@8.36.0) + version: 8.8.0(eslint@8.37.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + version: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) eslint-plugin-json: specifier: ^3.1.0 version: 3.1.0 eslint-plugin-prettier: specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.6) + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.37.0)(prettier@2.8.7) eslint-plugin-simple-import-sort: specifier: ^10.0.0 - version: 10.0.0(eslint@8.36.0) + version: 10.0.0(eslint@8.37.0) eslint-plugin-unused-imports: specifier: ^2.0.0 - version: 2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0) + version: 2.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint@8.37.0) magic-string: specifier: ^0.27.0 version: 0.27.0 @@ -1611,26 +1617,26 @@ importers: version: 4.0.2(postcss@8.4.20) rollup-plugin-ts: specifier: '*' - version: 3.0.2(@babel/core@7.21.3)(@babel/plugin-transform-runtime@7.21.0)(@babel/preset-env@7.20.2)(@babel/preset-typescript@7.21.0)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.2) + version: 3.0.2(@babel/core@7.21.3)(@babel/plugin-transform-runtime@7.21.4)(@babel/preset-env@7.21.4)(@babel/preset-typescript@7.21.4)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.3) vite: specifier: 4.2.1 - version: 4.2.1(@types/node@18.15.5) + version: 4.2.1(@types/node@18.15.11) vite-plugin-fonts: specifier: 0.7.0 version: 0.7.0(vite@4.2.1) devDependencies: '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 typescript: - specifier: ^5.0.2 - version: 5.0.2 + specifier: ^5.0.3 + version: 5.0.3 workspace/eslint: dependencies: '@types/eslint': - specifier: ^8.21.3 - version: 8.21.3 + specifier: ^8.37.0 + version: 8.37.0 '@typescript-eslint/eslint-plugin': specifier: ^5.56.0 version: 5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2) @@ -1675,8 +1681,8 @@ importers: version: 5.0.2 devDependencies: '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 workspace/json: dependencies: @@ -1775,8 +1781,8 @@ importers: specifier: workspace:* version: link:../build '@types/node': - specifier: 18.15.5 - version: 18.15.5 + specifier: 18.15.11 + version: 18.15.11 '@types/shell-escape-tag': specifier: workspace:^ version: link:../../@types/shell-escape-tag @@ -1829,8 +1835,8 @@ importers: specifier: ^10.2.1 version: 10.2.1 eslint: - specifier: ^8.36.0 - version: 8.36.0 + specifier: ^8.37.0 + version: 8.37.0 fast-glob: specifier: ^3.2.11 version: 3.2.12 @@ -1962,12 +1968,8 @@ packages: dependencies: '@babel/highlight': 7.18.6 - /@babel/compat-data@7.20.1: - resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==} - engines: {node: '>=6.9.0'} - - /@babel/compat-data@7.21.0: - resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} + /@babel/compat-data@7.21.4: + resolution: {integrity: sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==} engines: {node: '>=6.9.0'} /@babel/core@7.21.3: @@ -1977,13 +1979,13 @@ packages: '@ampproject/remapping': 2.2.0 '@babel/code-frame': 7.18.6 '@babel/generator': 7.21.3 - '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.21.3) + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.3) '@babel/helper-module-transforms': 7.21.2 '@babel/helpers': 7.21.0 '@babel/parser': 7.21.3 '@babel/template': 7.20.7 '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 convert-source-map: 1.9.0 debug: 4.3.4(supports-color@5.5.0) gensync: 1.0.0-beta.2 @@ -1992,7 +1994,7 @@ packages: transitivePeerDependencies: - supports-color - /@babel/eslint-parser@7.21.3(@babel/core@7.21.3)(eslint@8.36.0): + /@babel/eslint-parser@7.21.3(@babel/core@7.21.3)(eslint@8.37.0): resolution: {integrity: sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: @@ -2001,32 +2003,16 @@ packages: dependencies: '@babel/core': 7.21.3 '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.36.0 + eslint: 8.37.0 eslint-visitor-keys: 2.1.0 semver: 6.3.0 dev: true - /@babel/generator@7.20.4: - resolution: {integrity: sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.21.3 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - - /@babel/generator@7.20.7: - resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.21.3 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - /@babel/generator@7.21.3: resolution: {integrity: sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.17 jsesc: 2.5.2 @@ -2035,57 +2021,28 @@ packages: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-explode-assignable-expression': 7.18.6 - '@babel/types': 7.20.7 - - /@babel/helper-compilation-targets@7.20.0(@babel/core@7.21.3): - resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.20.1 - '@babel/core': 7.21.3 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - semver: 6.3.0 + '@babel/types': 7.21.4 - /@babel/helper-compilation-targets@7.20.7(@babel/core@7.21.3): - resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} + /@babel/helper-compilation-targets@7.21.4(@babel/core@7.21.3): + resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.21.0 + '@babel/compat-data': 7.21.4 '@babel/core': 7.21.3 '@babel/helper-validator-option': 7.21.0 browserslist: 4.21.4 lru-cache: 5.1.1 semver: 6.3.0 - /@babel/helper-create-class-features-plugin@7.20.7(@babel/core@7.21.3): - resolution: {integrity: sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.21.3 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-member-expression-to-functions': 7.20.7 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-split-export-declaration': 7.18.6 - transitivePeerDependencies: - - supports-color - /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.21.3): resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} engines: {node: '>=6.9.0'} @@ -2114,13 +2071,23 @@ packages: '@babel/helper-annotate-as-pure': 7.18.6 regexpu-core: 5.2.1 + /@babel/helper-create-regexp-features-plugin@7.21.4(@babel/core@7.21.3): + resolution: {integrity: sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.3 + '@babel/helper-annotate-as-pure': 7.18.6 + regexpu-core: 5.3.2 + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.3): resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 debug: 4.3.4(supports-color@5.5.0) lodash.debounce: 4.0.8 @@ -2137,73 +2104,58 @@ packages: resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 - - /@babel/helper-function-name@7.19.0: - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-function-name@7.21.0: resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-member-expression-to-functions@7.20.7: resolution: {integrity: sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-member-expression-to-functions@7.21.0: resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/helper-module-imports@7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 + dev: true - /@babel/helper-module-transforms@7.20.2: - resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} + /@babel/helper-module-imports@7.21.4: + resolution: {integrity: sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.20.2 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color + '@babel/types': 7.21.4 /@babel/helper-module-transforms@7.21.2: resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 + '@babel/helper-module-imports': 7.21.4 '@babel/helper-simple-access': 7.20.2 '@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.20.7 '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color @@ -2211,7 +2163,7 @@ packages: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-plugin-utils@7.20.2: resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} @@ -2227,7 +2179,7 @@ packages: '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-wrap-function': 7.19.0 - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color @@ -2240,7 +2192,7 @@ packages: '@babel/helper-optimise-call-expression': 7.18.6 '@babel/template': 7.20.7 '@babel/traverse': 7.20.10 - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color @@ -2248,19 +2200,19 @@ packages: resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-skip-transparent-expression-wrappers@7.20.0: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-split-export-declaration@7.18.6: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.20.7 + '@babel/types': 7.21.4 /@babel/helper-string-parser@7.19.4: resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} @@ -2273,6 +2225,7 @@ packages: /@babel/helper-validator-option@7.18.6: resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-validator-option@7.21.0: resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} @@ -2284,8 +2237,8 @@ packages: dependencies: '@babel/helper-function-name': 7.21.0 '@babel/template': 7.20.7 - '@babel/traverse': 7.20.10 - '@babel/types': 7.21.3 + '@babel/traverse': 7.21.3 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color @@ -2295,7 +2248,7 @@ packages: dependencies: '@babel/template': 7.20.7 '@babel/traverse': 7.21.3 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 transitivePeerDependencies: - supports-color @@ -2312,29 +2265,15 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.20.2 + '@babel/types': 7.21.4 dev: false - /@babel/parser@7.20.3: - resolution: {integrity: sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.21.3 - - /@babel/parser@7.20.7: - resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.21.3 - /@babel/parser@7.21.3: resolution: {integrity: sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} @@ -2345,8 +2284,8 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.18.9(@babel/core@7.21.3): - resolution: {integrity: sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==} + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 @@ -2354,10 +2293,10 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.3) - /@babel/plugin-proposal-async-generator-functions@7.20.1(@babel/core@7.21.3): - resolution: {integrity: sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==} + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2377,19 +2316,19 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - /@babel/plugin-proposal-class-static-block@7.18.6(@babel/core@7.21.3): - resolution: {integrity: sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==} + /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.3) transitivePeerDependencies: @@ -2441,8 +2380,8 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.3) - /@babel/plugin-proposal-logical-assignment-operators@7.18.9(@babel/core@7.21.3): - resolution: {integrity: sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==} + /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2471,18 +2410,18 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.3) - /@babel/plugin-proposal-object-rest-spread@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==} + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.20.1 + '@babel/compat-data': 7.21.4 '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.3) - '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.3) /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} @@ -2494,8 +2433,8 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.3) - /@babel/plugin-proposal-optional-chaining@7.18.9(@babel/core@7.21.3): - resolution: {integrity: sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==} + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2512,20 +2451,20 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - /@babel/plugin-proposal-private-property-in-object@7.18.6(@babel/core@7.21.3): - resolution: {integrity: sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==} + /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.20.7(@babel/core@7.21.3) + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) transitivePeerDependencies: @@ -2609,15 +2548,14 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.21.3): - resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} + /@babel/plugin-syntax-jsx@7.21.4(@babel/core@7.21.3): + resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - dev: true /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.3): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} @@ -2694,8 +2632,8 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-arrow-functions@7.18.6(@babel/core@7.21.3): - resolution: {integrity: sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==} + /@babel/plugin-transform-arrow-functions@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2703,14 +2641,14 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-async-to-generator@7.18.6(@babel/core@7.21.3): - resolution: {integrity: sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==} + /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-module-imports': 7.18.6 + '@babel/helper-module-imports': 7.21.4 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.21.3) transitivePeerDependencies: @@ -2725,8 +2663,8 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-block-scoping@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==} + /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2734,17 +2672,17 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-classes@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==} + /@babel/plugin-transform-classes@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.3) '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-optimise-call-expression': 7.18.6 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-replace-supers': 7.20.7 @@ -2753,17 +2691,18 @@ packages: transitivePeerDependencies: - supports-color - /@babel/plugin-transform-computed-properties@7.18.9(@babel/core@7.21.3): - resolution: {integrity: sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==} + /@babel/plugin-transform-computed-properties@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 + '@babel/template': 7.20.7 - /@babel/plugin-transform-destructuring@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==} + /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.21.3): + resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2800,8 +2739,8 @@ packages: '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-for-of@7.18.8(@babel/core@7.21.3): - resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} + /@babel/plugin-transform-for-of@7.21.0(@babel/core@7.21.3): + resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2816,8 +2755,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) - '@babel/helper-function-name': 7.19.0 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.3) + '@babel/helper-function-name': 7.21.0 '@babel/helper-plugin-utils': 7.20.2 /@babel/plugin-transform-literals@7.18.9(@babel/core@7.21.3): @@ -2838,40 +2777,40 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-modules-amd@7.19.6(@babel/core@7.21.3): - resolution: {integrity: sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==} + /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.21.3): + resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-module-transforms': 7.20.2 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - /@babel/plugin-transform-modules-commonjs@7.19.6(@babel/core@7.21.3): - resolution: {integrity: sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==} + /@babel/plugin-transform-modules-commonjs@7.21.2(@babel/core@7.21.3): + resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-module-transforms': 7.20.2 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-simple-access': 7.20.2 transitivePeerDependencies: - supports-color - /@babel/plugin-transform-modules-systemjs@7.19.6(@babel/core@7.21.3): - resolution: {integrity: sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==} + /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.21.3): + resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-module-transforms': 7.20.2 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-identifier': 7.19.1 transitivePeerDependencies: @@ -2884,19 +2823,19 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-module-transforms': 7.20.2 + '@babel/helper-module-transforms': 7.21.2 '@babel/helper-plugin-utils': 7.20.2 transitivePeerDependencies: - supports-color - /@babel/plugin-transform-named-capturing-groups-regex@7.19.1(@babel/core@7.21.3): - resolution: {integrity: sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==} + /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.21.3): + resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) + '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.21.3): @@ -2920,8 +2859,8 @@ packages: transitivePeerDependencies: - supports-color - /@babel/plugin-transform-parameters@7.20.3(@babel/core@7.21.3): - resolution: {integrity: sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==} + /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.21.3): + resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2966,10 +2905,10 @@ packages: dependencies: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-module-imports': 7.18.6 + '@babel/helper-module-imports': 7.21.4 '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.21.3) - '@babel/types': 7.20.2 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.3) + '@babel/types': 7.21.4 dev: true /@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.21.3): @@ -2983,15 +2922,15 @@ packages: '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-transform-regenerator@7.18.6(@babel/core@7.21.3): - resolution: {integrity: sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==} + /@babel/plugin-transform-regenerator@7.20.5(@babel/core@7.21.3): + resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - regenerator-transform: 0.15.0 + regenerator-transform: 0.15.1 /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.21.3): resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} @@ -3002,14 +2941,14 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-runtime@7.21.0(@babel/core@7.21.3): - resolution: {integrity: sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==} + /@babel/plugin-transform-runtime@7.21.4(@babel/core@7.21.3): + resolution: {integrity: sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-module-imports': 7.18.6 + '@babel/helper-module-imports': 7.21.4 '@babel/helper-plugin-utils': 7.20.2 babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) @@ -3027,8 +2966,8 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-transform-spread@7.19.0(@babel/core@7.21.3): - resolution: {integrity: sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==} + /@babel/plugin-transform-spread@7.20.7(@babel/core@7.21.3): + resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -3094,36 +3033,36 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.3 - '@babel/helper-create-regexp-features-plugin': 7.19.0(@babel/core@7.21.3) + '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - /@babel/preset-env@7.20.2(@babel/core@7.21.3): - resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} + /@babel/preset-env@7.21.4(@babel/core@7.21.3): + resolution: {integrity: sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.20.1 + '@babel/compat-data': 7.21.4 '@babel/core': 7.21.3 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.21.3) + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.3) '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.18.6 + '@babel/helper-validator-option': 7.21.0 '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-proposal-async-generator-functions': 7.20.1(@babel/core@7.21.3) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.21.3) '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-class-static-block': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.21.3) '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.21.3) '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.21.3) '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-logical-assignment-operators': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.21.3) '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.21.3) '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-object-rest-spread': 7.20.2(@babel/core@7.21.3) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.21.3) '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-optional-chaining': 7.18.9(@babel/core@7.21.3) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.3) '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-proposal-private-property-in-object': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.21.3) '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.3) '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.3) @@ -3140,40 +3079,40 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.3) '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.3) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.3) - '@babel/plugin-transform-arrow-functions': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-async-to-generator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-arrow-functions': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.21.3) '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-block-scoping': 7.20.2(@babel/core@7.21.3) - '@babel/plugin-transform-classes': 7.20.2(@babel/core@7.21.3) - '@babel/plugin-transform-computed-properties': 7.18.9(@babel/core@7.21.3) - '@babel/plugin-transform-destructuring': 7.20.2(@babel/core@7.21.3) + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-transform-computed-properties': 7.20.7(@babel/core@7.21.3) + '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.21.3) '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.21.3) '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-for-of': 7.18.8(@babel/core@7.21.3) + '@babel/plugin-transform-for-of': 7.21.0(@babel/core@7.21.3) '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.21.3) '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.21.3) '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-amd': 7.19.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-commonjs': 7.19.6(@babel/core@7.21.3) - '@babel/plugin-transform-modules-systemjs': 7.19.6(@babel/core@7.21.3) + '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.21.3) + '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.21.3) + '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.21.3) '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-named-capturing-groups-regex': 7.19.1(@babel/core@7.21.3) + '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.21.3) '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.21.3) '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-parameters': 7.20.3(@babel/core@7.21.3) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.21.3) '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-regenerator': 7.18.6(@babel/core@7.21.3) + '@babel/plugin-transform-regenerator': 7.20.5(@babel/core@7.21.3) '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.21.3) '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.21.3) - '@babel/plugin-transform-spread': 7.19.0(@babel/core@7.21.3) + '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.21.3) '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.21.3) '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.21.3) '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.21.3) '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.21.3) '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.21.3) '@babel/preset-modules': 0.1.5(@babel/core@7.21.3) - '@babel/types': 7.20.2 + '@babel/types': 7.21.4 babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3) babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.3) babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.3) @@ -3191,7 +3130,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.3) '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.21.3) - '@babel/types': 7.20.2 + '@babel/types': 7.21.4 esutils: 2.0.3 /@babel/preset-react@7.18.6(@babel/core@7.21.3): @@ -3209,8 +3148,8 @@ packages: '@babel/plugin-transform-react-pure-annotations': 7.18.6(@babel/core@7.21.3) dev: true - /@babel/preset-typescript@7.21.0(@babel/core@7.21.3): - resolution: {integrity: sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==} + /@babel/preset-typescript@7.21.4(@babel/core@7.21.3): + resolution: {integrity: sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -3218,10 +3157,15 @@ packages: '@babel/core': 7.21.3 '@babel/helper-plugin-utils': 7.20.2 '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.3) + '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.21.3) '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.3) transitivePeerDependencies: - supports-color + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + /@babel/runtime@7.21.0: resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} engines: {node: '>=6.9.0'} @@ -3233,21 +3177,21 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/parser': 7.20.7 - '@babel/types': 7.21.3 + '@babel/parser': 7.21.3 + '@babel/types': 7.21.4 /@babel/traverse@7.20.1(supports-color@5.5.0): resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.4 + '@babel/generator': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.3 - '@babel/types': 7.20.2 + '@babel/parser': 7.21.3 + '@babel/types': 7.21.4 debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: @@ -3258,13 +3202,13 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.7 + '@babel/generator': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.7 - '@babel/types': 7.21.3 + '@babel/parser': 7.21.3 + '@babel/types': 7.21.4 debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: @@ -3281,30 +3225,14 @@ packages: '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 '@babel/parser': 7.21.3 - '@babel/types': 7.21.3 + '@babel/types': 7.21.4 debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color - /@babel/types@7.20.2: - resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - - /@babel/types@7.20.7: - resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - - /@babel/types@7.21.3: - resolution: {integrity: sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==} + /@babel/types@7.21.4: + resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.19.4 @@ -3324,7 +3252,7 @@ packages: fs-extra: 7.0.1 lodash.startcase: 4.4.0 outdent: 0.5.0 - prettier: 2.8.6 + prettier: 2.8.7 resolve-from: 5.0.0 semver: 5.7.1 dev: true @@ -3492,7 +3420,7 @@ packages: '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 - prettier: 2.8.6 + prettier: 2.8.7 dev: true /@colors/colors@1.5.0: @@ -3545,7 +3473,7 @@ packages: resolution: {integrity: sha512-DBBCiHPgL2B/elUpvCDhNHXnlZQ9sfO2uyt1OJyAXKT41beQEFY4OxZ6gwS+ZesRCbZ6JV8M7GEyOPkjv8kdIw==} dependencies: '@esbuild-kit/core-utils': 3.0.0 - get-tsconfig: 4.2.0 + get-tsconfig: 4.5.0 dev: true /@esbuild-kit/core-utils@3.0.0: @@ -3559,7 +3487,7 @@ packages: resolution: {integrity: sha512-ySs0qOsiwj+hsgZM9/MniGdvfa9/WzqfFuIia8/5gSUPeIQIX2/tG91QakxPFOR35VFiwTB7wCiHtiS6dc6SkA==} dependencies: '@esbuild-kit/core-utils': 3.0.0 - get-tsconfig: 4.2.0 + get-tsconfig: 4.5.0 dev: true /@esbuild-plugins/node-globals-polyfill@0.1.1(esbuild@0.17.12): @@ -3770,7 +3698,16 @@ packages: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: eslint: 8.36.0 - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.0 + + /@eslint-community/eslint-utils@4.3.0(eslint@8.37.0): + resolution: {integrity: sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.37.0 + eslint-visitor-keys: 3.4.0 /@eslint-community/regexpp@4.4.0: resolution: {integrity: sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==} @@ -3799,7 +3736,23 @@ packages: dependencies: ajv: 6.12.6 debug: 4.3.4(supports-color@5.5.0) - espree: 9.5.0 + espree: 9.5.1 + globals: 13.19.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + /@eslint/eslintrc@2.0.2: + resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4(supports-color@5.5.0) + espree: 9.5.1 globals: 13.19.0 ignore: 5.2.0 import-fresh: 3.3.0 @@ -3813,6 +3766,10 @@ packages: resolution: {integrity: sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@eslint/js@8.37.0: + resolution: {integrity: sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@faker-js/faker@7.6.0: resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} engines: {node: '>=14.0.0', npm: '>=6.0.0'} @@ -3871,7 +3828,7 @@ packages: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: '@babel/runtime': 7.21.0 - '@types/node': 18.15.5 + '@types/node': 18.15.11 find-up: 4.1.0 fs-extra: 8.1.0 dev: true @@ -4018,8 +3975,8 @@ packages: dependencies: '@shopify/polaris-icons': 6.7.0 '@shopify/polaris-tokens': 6.3.0 - '@types/react': 18.0.26 - '@types/react-dom': 18.0.10 + '@types/react': 18.0.33 + '@types/react-dom': 18.0.11 '@types/react-transition-group': 4.4.5 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -4088,7 +4045,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 '@testing-library/dom': 8.19.0 - '@types/react-dom': 18.0.10 + '@types/react-dom': 18.0.11 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true @@ -4102,7 +4059,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 '@testing-library/dom': 9.0.1 - '@types/react-dom': 18.0.10 + '@types/react-dom': 18.0.11 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true @@ -4131,8 +4088,8 @@ packages: /@types/chai@4.3.4: resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} - /@types/eslint@8.21.3: - resolution: {integrity: sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==} + /@types/eslint@8.37.0: + resolution: {integrity: sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==} dependencies: '@types/estree': 1.0.0 '@types/json-schema': 7.0.11 @@ -4144,13 +4101,13 @@ packages: resolution: {integrity: sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 18.15.5 + '@types/node': 18.15.11 dev: true /@types/hoist-non-react-statics@3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: - '@types/react': 18.0.28 + '@types/react': 18.0.33 hoist-non-react-statics: 3.3.2 dev: true @@ -4178,8 +4135,8 @@ packages: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node@18.15.5: - resolution: {integrity: sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==} + /@types/node@18.15.11: + resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -4207,16 +4164,22 @@ packages: '@types/react': 18.0.26 dev: true + /@types/react-dom@18.0.11: + resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==} + dependencies: + '@types/react': 18.0.33 + dev: true + /@types/react-portal@4.0.4: resolution: {integrity: sha512-ecVWngYHeSymq5XdrQOXRpIb9ay5SM4Stm/ur6+wc0Z+r05gafZ5SuMRbXKYsj4exNJa+4CTKK6J7qcTKm9K5g==} dependencies: - '@types/react': 18.0.26 + '@types/react': 18.0.33 dev: true /@types/react-transition-group@4.4.5: resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==} dependencies: - '@types/react': 18.0.28 + '@types/react': 18.0.33 dev: true /@types/react@18.0.26: @@ -4227,8 +4190,8 @@ packages: csstype: 3.1.1 dev: true - /@types/react@18.0.28: - resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==} + /@types/react@18.0.33: + resolution: {integrity: sha512-sHxzVxeanvQyQ1lr8NSHaj0kDzcNiGpILEVt69g9S31/7PfMvNCKLKcsHw4lYKjs3cGNJjXSP4mYzX43QlnjNA==} dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.2 @@ -4254,20 +4217,20 @@ packages: resolution: {integrity: sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==} dependencies: '@types/glob': 8.0.0 - '@types/node': 18.15.5 + '@types/node': 18.15.11 dev: true /@types/split2@3.2.1: resolution: {integrity: sha512-7uz3yU+LooBq4yNOzlZD9PU9/1Eu0rTD1MjQ6apOVEoHsPrMUrFw7W8XrvWtesm2vK67SBK9AyJcOXtMpl9bgQ==} dependencies: - '@types/node': 18.15.5 + '@types/node': 18.15.11 dev: true /@types/styled-components@5.1.26: resolution: {integrity: sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==} dependencies: '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 18.0.26 + '@types/react': 18.0.33 csstype: 3.1.1 dev: true @@ -4305,6 +4268,34 @@ packages: typescript: 5.0.2 transitivePeerDependencies: - supports-color + dev: false + + /@typescript-eslint/eslint-plugin@5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3): + resolution: {integrity: sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.4.0 + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/scope-manager': 5.57.1 + '@typescript-eslint/type-utils': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + debug: 4.3.4(supports-color@5.5.0) + eslint: 8.37.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.0 + natural-compare-lite: 1.4.0 + semver: 7.3.8 + tsutils: 3.21.0(typescript@5.0.3) + typescript: 5.0.3 + transitivePeerDependencies: + - supports-color /@typescript-eslint/parser@5.56.0(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==} @@ -4325,6 +4316,25 @@ packages: transitivePeerDependencies: - supports-color + /@typescript-eslint/parser@5.57.1(eslint@8.37.0)(typescript@5.0.3): + resolution: {integrity: sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.57.1 + '@typescript-eslint/types': 5.57.1 + '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.3) + debug: 4.3.4(supports-color@5.5.0) + eslint: 8.37.0 + typescript: 5.0.3 + transitivePeerDependencies: + - supports-color + /@typescript-eslint/scope-manager@5.56.0: resolution: {integrity: sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4332,6 +4342,13 @@ packages: '@typescript-eslint/types': 5.56.0 '@typescript-eslint/visitor-keys': 5.56.0 + /@typescript-eslint/scope-manager@5.57.1: + resolution: {integrity: sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.57.1 + '@typescript-eslint/visitor-keys': 5.57.1 + /@typescript-eslint/type-utils@5.56.0(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4350,11 +4367,35 @@ packages: typescript: 5.0.2 transitivePeerDependencies: - supports-color + dev: false + + /@typescript-eslint/type-utils@5.57.1(eslint@8.37.0)(typescript@5.0.3): + resolution: {integrity: sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.3) + '@typescript-eslint/utils': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + debug: 4.3.4(supports-color@5.5.0) + eslint: 8.37.0 + tsutils: 3.21.0(typescript@5.0.3) + typescript: 5.0.3 + transitivePeerDependencies: + - supports-color /@typescript-eslint/types@5.56.0: resolution: {integrity: sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/types@5.57.1: + resolution: {integrity: sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/typescript-estree@5.56.0(typescript@5.0.2): resolution: {integrity: sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4375,6 +4416,26 @@ packages: transitivePeerDependencies: - supports-color + /@typescript-eslint/typescript-estree@5.57.1(typescript@5.0.3): + resolution: {integrity: sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.57.1 + '@typescript-eslint/visitor-keys': 5.57.1 + debug: 4.3.4(supports-color@5.5.0) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.8 + tsutils: 3.21.0(typescript@5.0.3) + typescript: 5.0.3 + transitivePeerDependencies: + - supports-color + /@typescript-eslint/utils@5.56.0(eslint@8.36.0)(typescript@5.0.2): resolution: {integrity: sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4393,13 +4454,40 @@ packages: transitivePeerDependencies: - supports-color - typescript + dev: false + + /@typescript-eslint/utils@5.57.1(eslint@8.37.0)(typescript@5.0.3): + resolution: {integrity: sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.3.0(eslint@8.37.0) + '@types/json-schema': 7.0.11 + '@types/semver': 7.3.13 + '@typescript-eslint/scope-manager': 5.57.1 + '@typescript-eslint/types': 5.57.1 + '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.0.3) + eslint: 8.37.0 + eslint-scope: 5.1.1 + semver: 7.3.8 + transitivePeerDependencies: + - supports-color + - typescript /@typescript-eslint/visitor-keys@5.56.0: resolution: {integrity: sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.56.0 - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.0 + + /@typescript-eslint/visitor-keys@5.57.1: + resolution: {integrity: sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.57.1 + eslint-visitor-keys: 3.4.0 /@vitest/expect@0.29.7: resolution: {integrity: sha512-UtG0tW0DP6b3N8aw7PHmweKDsvPv4wjGvrVZW7OSxaFg76ShtVdMiMcUkZJgCE8QWUmhwaM0aQhbbVLo4F4pkA==} @@ -4481,7 +4569,7 @@ packages: /@vue/compiler-core@3.2.41: resolution: {integrity: sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==} dependencies: - '@babel/parser': 7.20.3 + '@babel/parser': 7.21.3 '@vue/shared': 3.2.41 estree-walker: 2.0.2 source-map: 0.6.1 @@ -4497,7 +4585,7 @@ packages: /@vue/compiler-sfc@3.2.41: resolution: {integrity: sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==} dependencies: - '@babel/parser': 7.20.3 + '@babel/parser': 7.21.3 '@vue/compiler-core': 3.2.41 '@vue/compiler-dom': 3.2.41 '@vue/compiler-ssr': 3.2.41 @@ -4519,7 +4607,7 @@ packages: /@vue/reactivity-transform@3.2.41: resolution: {integrity: sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==} dependencies: - '@babel/parser': 7.20.3 + '@babel/parser': 7.21.3 '@vue/compiler-core': 3.2.41 '@vue/shared': 3.2.41 estree-walker: 2.0.2 @@ -4748,7 +4836,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.20.1 + '@babel/compat-data': 7.21.4 '@babel/core': 7.21.3 '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.3) semver: 6.3.0 @@ -4782,7 +4870,7 @@ packages: styled-components: '>= 2' dependencies: '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-module-imports': 7.18.6 + '@babel/helper-module-imports': 7.21.4 babel-plugin-syntax-jsx: 6.18.0 lodash: 4.17.21 picomatch: 2.3.1 @@ -5116,14 +5204,14 @@ packages: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} dev: false - /compatfactory@1.0.1(typescript@5.0.2): + /compatfactory@1.0.1(typescript@5.0.3): resolution: {integrity: sha512-hR9u0HSZTKDNNchPtMHg6myeNx0XO+av7UZIJPsi4rPALJBHi/W5Mbwi19hC/xm6y3JkYpxVYjTqnSGsU5X/iw==} engines: {node: '>=14.9.0'} peerDependencies: typescript: '*' dependencies: helpertypes: 0.0.18 - typescript: 5.0.2 + typescript: 5.0.3 dev: false /concat-map@0.0.1: @@ -5195,7 +5283,7 @@ packages: resolution: {integrity: sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA==} engines: {node: '>=14.9.0'} dependencies: - '@types/node': 18.15.5 + '@types/node': 18.15.11 dev: false /css-color-keywords@1.0.0: @@ -5658,6 +5746,13 @@ packages: graceful-fs: 4.2.10 tapable: 2.2.1 + /enhanced-resolve@5.12.0: + resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.10 + tapable: 2.2.1 + /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} @@ -6000,7 +6095,7 @@ packages: optionalDependencies: source-map: 0.6.1 - /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.27.5)(eslint@8.36.0): + /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.27.5)(eslint@8.37.0): resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -6008,14 +6103,14 @@ packages: eslint-plugin-import: ^2.25.2 dependencies: confusing-browser-globals: 1.0.11 - eslint: 8.36.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint: 8.37.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) object.assign: 4.1.4 object.entries: 1.1.6 semver: 6.3.0 dev: true - /eslint-config-airbnb@19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.36.0): + /eslint-config-airbnb@19.0.4(eslint-plugin-import@2.27.5)(eslint-plugin-jsx-a11y@6.7.1)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.32.2)(eslint@8.37.0): resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -6025,12 +6120,12 @@ packages: eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 dependencies: - eslint: 8.36.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.36.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) - eslint-plugin-jsx-a11y: 6.7.1(eslint@8.36.0) - eslint-plugin-react: 7.32.2(eslint@8.36.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.36.0) + eslint: 8.37.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.37.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) + eslint-plugin-jsx-a11y: 6.7.1(eslint@8.37.0) + eslint-plugin-react: 7.32.2(eslint@8.37.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.37.0) object.assign: 4.1.4 object.entries: 1.1.6 dev: true @@ -6042,6 +6137,15 @@ packages: eslint: '>=7.0.0' dependencies: eslint: 8.36.0 + dev: false + + /eslint-config-prettier@8.8.0(eslint@8.37.0): + resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.37.0 /eslint-import-resolver-node@0.3.7: resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} @@ -6071,6 +6175,29 @@ packages: transitivePeerDependencies: - supports-color + /eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.57.1)(eslint-plugin-import@2.27.5)(eslint@8.37.0): + resolution: {integrity: sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4(supports-color@5.5.0) + enhanced-resolve: 5.12.0 + eslint: 8.37.0 + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) + get-tsconfig: 4.5.0 + globby: 13.1.3 + is-core-module: 2.11.0 + is-glob: 4.0.3 + synckit: 0.8.5 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} @@ -6100,6 +6227,35 @@ packages: transitivePeerDependencies: - supports-color + /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0): + resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + debug: 3.2.7 + eslint: 8.37.0 + eslint-import-resolver-node: 0.3.7 + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.57.1)(eslint-plugin-import@2.27.5)(eslint@8.37.0) + transitivePeerDependencies: + - supports-color + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.56.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} @@ -6132,6 +6288,38 @@ packages: - eslint-import-resolver-webpack - supports-color + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0): + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.57.1(eslint@8.37.0)(typescript@5.0.3) + array-includes: 3.1.6 + array.prototype.flat: 1.3.1 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.37.0 + eslint-import-resolver-node: 0.3.7 + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.37.0) + has: 1.0.3 + is-core-module: 2.11.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.6 + resolve: 1.22.1 + semver: 6.3.0 + tsconfig-paths: 3.14.1 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + /eslint-plugin-json@3.1.0: resolution: {integrity: sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==} engines: {node: '>=12.0'} @@ -6150,8 +6338,21 @@ packages: eslint: 8.36.0 jsonc-eslint-parser: 2.1.0 natural-compare: 1.4.0 + dev: false - /eslint-plugin-jsx-a11y@6.7.1(eslint@8.36.0): + /eslint-plugin-jsonc@2.7.0(eslint@8.37.0): + resolution: {integrity: sha512-DZgC71h/hZ9t5k/OGAKOMdJCleg2neZLL7No+YYi2ZMroCN4X5huZdrLf1USbrc6UTHwYujd1EDwXHg1qJ6CYw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.3.0(eslint@8.37.0) + eslint: 8.37.0 + jsonc-eslint-parser: 2.1.0 + natural-compare: 1.4.0 + dev: true + + /eslint-plugin-jsx-a11y@6.7.1(eslint@8.37.0): resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} engines: {node: '>=4.0'} peerDependencies: @@ -6166,7 +6367,7 @@ packages: axobject-query: 3.1.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 8.36.0 + eslint: 8.37.0 has: 1.0.3 jsx-ast-utils: 3.3.3 language-tags: 1.0.5 @@ -6191,17 +6392,34 @@ packages: eslint-config-prettier: 8.8.0(eslint@8.36.0) prettier: 2.8.6 prettier-linter-helpers: 1.0.0 + dev: false - /eslint-plugin-react-hooks@4.6.0(eslint@8.36.0): + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.37.0)(prettier@2.8.7): + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.37.0 + eslint-config-prettier: 8.8.0(eslint@8.37.0) + prettier: 2.8.7 + prettier-linter-helpers: 1.0.0 + + /eslint-plugin-react-hooks@4.6.0(eslint@8.37.0): resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 dependencies: - eslint: 8.36.0 + eslint: 8.37.0 dev: true - /eslint-plugin-react@7.32.2(eslint@8.36.0): + /eslint-plugin-react@7.32.2(eslint@8.37.0): resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==} engines: {node: '>=4'} peerDependencies: @@ -6211,7 +6429,7 @@ packages: array.prototype.flatmap: 1.3.1 array.prototype.tosorted: 1.1.1 doctrine: 2.1.0 - eslint: 8.36.0 + eslint: 8.37.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.3 minimatch: 3.1.2 @@ -6231,6 +6449,14 @@ packages: eslint: '>=5.0.0' dependencies: eslint: 8.36.0 + dev: false + + /eslint-plugin-simple-import-sort@10.0.0(eslint@8.37.0): + resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} + peerDependencies: + eslint: '>=5.0.0' + dependencies: + eslint: 8.37.0 /eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.56.0)(eslint@8.36.0): resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} @@ -6245,6 +6471,21 @@ packages: '@typescript-eslint/eslint-plugin': 5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@5.0.2) eslint: 8.36.0 eslint-rule-composer: 0.3.0 + dev: false + + /eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint@8.37.0): + resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.0.0 + eslint: ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.37.0)(typescript@5.0.3) + eslint: 8.37.0 + eslint-rule-composer: 0.3.0 /eslint-rule-composer@0.3.0: resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} @@ -6273,6 +6514,10 @@ packages: resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint-visitor-keys@3.4.0: + resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /eslint@8.36.0: resolution: {integrity: sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -6321,6 +6566,54 @@ packages: transitivePeerDependencies: - supports-color + /eslint@8.37.0: + resolution: {integrity: sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.3.0(eslint@8.37.0) + '@eslint-community/regexpp': 4.4.0 + '@eslint/eslintrc': 2.0.2 + '@eslint/js': 8.37.0 + '@humanwhocodes/config-array': 0.11.8 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4(supports-color@5.5.0) + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.1.1 + eslint-visitor-keys: 3.4.0 + espree: 9.5.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.19.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-sdsl: 4.1.5 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + /esno@0.16.3: resolution: {integrity: sha512-6slSBEV1lMKcX13DBifvnDFpNno5WXhw4j/ff7RI0y51BZiDqEe5dNhhjhIQ3iCOQuzsm2MbVzmwqbN78BBhPg==} hasBin: true @@ -6334,7 +6627,7 @@ packages: dependencies: acorn: 8.8.2 acorn-jsx: 5.3.2(acorn@8.8.2) - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.0 dev: false /espree@9.5.0: @@ -6343,7 +6636,15 @@ packages: dependencies: acorn: 8.8.2 acorn-jsx: 5.3.2(acorn@8.8.2) - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.0 + + /espree@9.5.1: + resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.2 + acorn-jsx: 5.3.2(acorn@8.8.2) + eslint-visitor-keys: 3.4.0 /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} @@ -6584,6 +6885,9 @@ packages: /get-tsconfig@4.2.0: resolution: {integrity: sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==} + /get-tsconfig@4.5.0: + resolution: {integrity: sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==} + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -6651,6 +6955,16 @@ packages: merge2: 1.4.1 slash: 4.0.0 + /globby@13.1.3: + resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 4.0.0 + /globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -6665,18 +6979,15 @@ packages: /grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - /happy-dom@8.9.0: - resolution: {integrity: sha512-JZwJuGdR7ko8L61136YzmrLv7LgTh5b8XaEM3P709mLjyQuXJ3zHTDXvUtBBahRjGlcYW0zGjIiEWizoTUGKfA==} + /happy-dom@9.1.9: + resolution: {integrity: sha512-OMbnoknA7iNNG/5fwt1JckCKc53QLLFo2ljzit1pCV9SC1TYwcQj0obq0QUTeqIf2p2skbFG69bo19YoSj/1DA==} dependencies: css.escape: 1.5.1 he: 1.2.0 iconv-lite: 0.6.3 - node-fetch: 2.6.7 webidl-conversions: 7.0.0 whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 - transitivePeerDependencies: - - encoding /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} @@ -7555,17 +7866,6 @@ packages: /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - /node-fetch@2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - /node-pty@0.10.1: resolution: {integrity: sha512-JTdtUS0Im/yRsWJSx7yiW9rtpfmxqxolrtnyKwPLI+6XqTAPW/O2MjS8FYL4I5TsMbH2lVgDb2VMjp+9LoQGNg==} requiresBuild: true @@ -8305,6 +8605,12 @@ packages: resolution: {integrity: sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==} engines: {node: '>=10.13.0'} hasBin: true + dev: false + + /prettier@2.8.7: + resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==} + engines: {node: '>=10.13.0'} + hasBin: true /pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} @@ -8506,8 +8812,8 @@ packages: /regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - /regenerator-transform@0.15.0: - resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} + /regenerator-transform@0.15.1: + resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} dependencies: '@babel/runtime': 7.21.0 @@ -8530,6 +8836,17 @@ packages: unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.0.0 + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.0 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + /regjsgen@0.7.1: resolution: {integrity: sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==} @@ -8622,7 +8939,7 @@ packages: - ts-node dev: false - /rollup-plugin-ts@3.0.2(@babel/core@7.21.3)(@babel/plugin-transform-runtime@7.21.0)(@babel/preset-env@7.20.2)(@babel/preset-typescript@7.21.0)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.2): + /rollup-plugin-ts@3.0.2(@babel/core@7.21.3)(@babel/plugin-transform-runtime@7.21.4)(@babel/preset-env@7.21.4)(@babel/preset-typescript@7.21.4)(@babel/runtime@7.21.0)(rollup@3.9.1)(typescript@5.0.3): resolution: {integrity: sha512-67qi2QTHewhLyKDG6fX3jpohWpmUPPIT/xJ7rsYK46X6MqmoWy64Ti0y8ygPfLv8mXDCdRZUofM3mTxDfCswRA==} engines: {node: '>=14.9.0', npm: '>=7.0.0', pnpm: '>=3.2.0', yarn: '>=1.13'} peerDependencies: @@ -8652,22 +8969,22 @@ packages: optional: true dependencies: '@babel/core': 7.21.3 - '@babel/plugin-transform-runtime': 7.21.0(@babel/core@7.21.3) - '@babel/preset-env': 7.20.2(@babel/core@7.21.3) - '@babel/preset-typescript': 7.21.0(@babel/core@7.21.3) + '@babel/plugin-transform-runtime': 7.21.4(@babel/core@7.21.3) + '@babel/preset-env': 7.21.4(@babel/core@7.21.3) + '@babel/preset-typescript': 7.21.4(@babel/core@7.21.3) '@babel/runtime': 7.21.0 '@rollup/pluginutils': 4.2.1 '@wessberg/stringutil': 1.0.19 ansi-colors: 4.1.3 browserslist: 4.21.4 browserslist-generator: 1.0.66 - compatfactory: 1.0.1(typescript@5.0.2) + compatfactory: 1.0.1(typescript@5.0.3) crosspath: 2.0.0 magic-string: 0.26.7 rollup: 3.9.1 - ts-clone-node: 1.0.0(typescript@5.0.2) + ts-clone-node: 1.0.0(typescript@5.0.3) tslib: 2.5.0 - typescript: 5.0.2 + typescript: 5.0.3 dev: false /rollup-pluginutils@2.8.2: @@ -9111,6 +9428,13 @@ packages: '@pkgr/utils': 2.3.1 tslib: 2.5.0 + /synckit@0.8.5: + resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/utils': 2.3.1 + tslib: 2.5.0 + /tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} @@ -9174,9 +9498,6 @@ packages: universalify: 0.2.0 url-parse: 1.5.10 - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} @@ -9194,14 +9515,14 @@ packages: engines: {node: '>=8'} dev: true - /ts-clone-node@1.0.0(typescript@5.0.2): + /ts-clone-node@1.0.0(typescript@5.0.3): resolution: {integrity: sha512-/cDYbr2HAXxFNeTT41c/xs/2bhLJjqnYheHsmA3AoHSt+n4JA4t0FL9Lk5O8kWnJ6jeB3kPcUoXIFtwERNzv6Q==} engines: {node: '>=14.9.0'} peerDependencies: typescript: '*' dependencies: - compatfactory: 1.0.1(typescript@5.0.2) - typescript: 5.0.2 + compatfactory: 1.0.1(typescript@5.0.3) + typescript: 5.0.3 dev: false /tsconfig-paths@3.14.1: @@ -9227,6 +9548,15 @@ packages: tslib: 1.14.1 typescript: 5.0.2 + /tsutils@3.21.0(typescript@5.0.3): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '*' + dependencies: + tslib: 1.14.1 + typescript: 5.0.3 + /tsx@3.11.0: resolution: {integrity: sha512-q+q4xxu41+AafVwvAGqtNJ1ekPFd33ZhTMXvgIpHMqv/W89efwDRE9IyjhEAZm5iTHsshKaf1BYWSk789BrNCA==} hasBin: true @@ -9292,6 +9622,11 @@ packages: engines: {node: '>=12.20'} hasBin: true + /typescript@5.0.3: + resolution: {integrity: sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==} + engines: {node: '>=12.20'} + hasBin: true + /ua-parser-js@1.0.32: resolution: {integrity: sha512-dXVsz3M4j+5tTiovFVyVqssXBu5HM47//YSOeZ9fQkdDKkfzv2v3PP1jmH6FUyPW+yCSn7aBVK1fGGKNhowdDA==} dev: false @@ -9326,6 +9661,10 @@ packages: resolution: {integrity: sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==} engines: {node: '>=4'} + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + /unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} @@ -9376,7 +9715,7 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite-node@0.29.7(@types/node@18.15.5): + /vite-node@0.29.7(@types/node@18.15.11): resolution: {integrity: sha512-PakCZLvz37yFfUPWBnLa1OYHPCGm5v4pmRrTcFN4V/N/T3I6tyP3z07S//9w+DdeL7vVd0VSeyMZuAh+449ZWw==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9386,7 +9725,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.2.1(@types/node@18.15.5) + vite: 4.2.1(@types/node@18.15.11) transitivePeerDependencies: - '@types/node' - less @@ -9396,7 +9735,7 @@ packages: - supports-color - terser - /vite-node@0.29.8(@types/node@18.15.5): + /vite-node@0.29.8(@types/node@18.15.11): resolution: {integrity: sha512-b6OtCXfk65L6SElVM20q5G546yu10/kNrhg08afEoWlFRJXFq9/6glsvSVY+aI6YeC1tu2TtAqI2jHEQmOmsFw==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9406,7 +9745,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.2.1(@types/node@18.15.5) + vite: 4.2.1(@types/node@18.15.11) transitivePeerDependencies: - '@types/node' - less @@ -9423,7 +9762,7 @@ packages: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 dependencies: fast-glob: 3.2.12 - vite: 4.2.1(@types/node@18.15.5) + vite: 4.2.1(@types/node@18.15.11) /vite-plugin-mpa@1.1.4: resolution: {integrity: sha512-sLXMOdMl8t9B9/sxXXZ9CLt8QudhGSSKCX+bZ/ePaO7kp4SdoA5d6CV+EnCyNuQCenAbXKJzk3nM8Do0RgmSpA==} @@ -9433,7 +9772,7 @@ packages: yargs: 16.2.0 dev: true - /vite@4.2.1(@types/node@18.15.5): + /vite@4.2.1(@types/node@18.15.11): resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -9458,7 +9797,7 @@ packages: terser: optional: true dependencies: - '@types/node': 18.15.5 + '@types/node': 18.15.11 esbuild: 0.17.12 postcss: 8.4.21 resolve: 1.22.1 @@ -9466,7 +9805,7 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vitest@0.29.7(@vitest/ui@0.29.7)(happy-dom@8.9.0)(jsdom@21.1.1): + /vitest@0.29.7(@vitest/ui@0.29.7)(happy-dom@9.1.9)(jsdom@21.1.1): resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9496,7 +9835,7 @@ packages: dependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 - '@types/node': 18.15.5 + '@types/node': 18.15.11 '@vitest/expect': 0.29.7 '@vitest/runner': 0.29.7 '@vitest/spy': 0.29.7 @@ -9507,7 +9846,7 @@ packages: cac: 6.7.14 chai: 4.3.7 debug: 4.3.4(supports-color@5.5.0) - happy-dom: 8.9.0 + happy-dom: 9.1.9 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 @@ -9518,8 +9857,8 @@ packages: tinybench: 2.3.1 tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.2.1(@types/node@18.15.5) - vite-node: 0.29.7(@types/node@18.15.5) + vite: 4.2.1(@types/node@18.15.11) + vite-node: 0.29.7(@types/node@18.15.11) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9530,7 +9869,7 @@ packages: - terser dev: true - /vitest@0.29.7(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1): + /vitest@0.29.7(@vitest/ui@0.29.8)(happy-dom@9.1.9)(jsdom@21.1.1): resolution: {integrity: sha512-aWinOSOu4jwTuZHkb+cCyrqQ116Q9TXaJrNKTHudKBknIpR0VplzeaOUuDF9jeZcrbtQKZQt6yrtd+eakbaxHg==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9560,7 +9899,7 @@ packages: dependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 - '@types/node': 18.15.5 + '@types/node': 18.15.11 '@vitest/expect': 0.29.7 '@vitest/runner': 0.29.7 '@vitest/spy': 0.29.7 @@ -9571,7 +9910,7 @@ packages: cac: 6.7.14 chai: 4.3.7 debug: 4.3.4(supports-color@5.5.0) - happy-dom: 8.9.0 + happy-dom: 9.1.9 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 @@ -9582,8 +9921,8 @@ packages: tinybench: 2.3.1 tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.2.1(@types/node@18.15.5) - vite-node: 0.29.7(@types/node@18.15.5) + vite: 4.2.1(@types/node@18.15.11) + vite-node: 0.29.7(@types/node@18.15.11) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9594,7 +9933,7 @@ packages: - terser dev: false - /vitest@0.29.8(@vitest/ui@0.29.8)(happy-dom@8.9.0)(jsdom@21.1.1): + /vitest@0.29.8(@vitest/ui@0.29.8)(happy-dom@9.1.9)(jsdom@21.1.1): resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==} engines: {node: '>=v14.16.0'} hasBin: true @@ -9627,7 +9966,7 @@ packages: dependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 - '@types/node': 18.15.5 + '@types/node': 18.15.11 '@vitest/expect': 0.29.8 '@vitest/runner': 0.29.8 '@vitest/spy': 0.29.8 @@ -9638,7 +9977,7 @@ packages: cac: 6.7.14 chai: 4.3.7 debug: 4.3.4(supports-color@5.5.0) - happy-dom: 8.9.0 + happy-dom: 9.1.9 jsdom: 21.1.1 local-pkg: 0.4.2 pathe: 1.1.0 @@ -9649,8 +9988,8 @@ packages: tinybench: 2.3.1 tinypool: 0.4.0 tinyspy: 1.0.2 - vite: 4.2.1(@types/node@18.15.5) - vite-node: 0.29.8(@types/node@18.15.5) + vite: 4.2.1(@types/node@18.15.11) + vite-node: 0.29.8(@types/node@18.15.11) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -9699,9 +10038,6 @@ packages: defaults: 1.0.4 dev: true - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -9730,12 +10066,6 @@ packages: tr46: 4.1.1 webidl-conversions: 7.0.0 - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: From 41f60923cb43b82b5ac913091b377c4038a6bf3f Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Sun, 9 Apr 2023 19:06:42 -0700 Subject: [PATCH 32/46] React cleanup --- packages/react/react/index.ts | 7 +- packages/react/react/src/context-provider.ts | 1 - packages/react/react/src/element.ts | 16 +- packages/react/react/src/starbeam/handlers.ts | 43 ++++++ packages/react/react/src/starbeam/instance.ts | 141 ++++++++++++++++++ .../react/react/src/use-component-instance.ts | 25 ++++ packages/react/react/src/use-reactive.ts | 28 +++- packages/react/react/src/use-resource.ts | 20 +-- packages/react/react/src/use-setup.ts | 6 +- packages/react/react/src/use-starbeam.ts | 41 +++++ .../react/react/tests/use-reactive.spec.ts | 5 - .../react/react/tests/use-service.spec.ts | 1 - .../react/tests/use-starbeam-app.spec.ts | 63 ++++++++ .../react/react/tests/use-starbeam.spec.ts | 84 +++++++++++ packages/react/test-utils/src/modes.ts | 1 + packages/react/use-strict-lifecycle/index.ts | 1 + .../use-strict-lifecycle/src/resource.ts | 129 ++++++++++------ .../tests/is-rendering.spec.ts | 2 +- .../tests/use-lifecycle.spec.ts | 31 ++-- .../debug/src/call-stack/debug/module.ts | 1 - .../src/description/debug/description.ts | 1 - packages/universal/resource/src/api.ts | 6 +- .../universal/runtime/src/context/context.ts | 25 ++-- .../universal/runtime/tests/protocol.spec.ts | 3 - packages/universal/service/src/service.ts | 26 +++- packages/universal/verify/index.ts | 16 +- packages/universal/verify/src/verify.ts | 27 ++-- 27 files changed, 597 insertions(+), 153 deletions(-) create mode 100644 packages/react/react/src/starbeam/handlers.ts create mode 100644 packages/react/react/src/starbeam/instance.ts create mode 100644 packages/react/react/src/use-component-instance.ts create mode 100644 packages/react/react/src/use-starbeam.ts create mode 100644 packages/react/react/tests/use-starbeam-app.spec.ts create mode 100644 packages/react/react/tests/use-starbeam.spec.ts diff --git a/packages/react/react/index.ts b/packages/react/react/index.ts index 2e3ef870..238df597 100644 --- a/packages/react/react/index.ts +++ b/packages/react/react/index.ts @@ -1,10 +1,15 @@ import "./src/debug/warnings.js"; -export { Starbeam } from "./src/context-provider.js"; +export { + type ReactApp, + Starbeam, + useStarbeamApp, +} from "./src/context-provider.js"; export * from "./src/element.js"; export * from "./src/ref.js"; export { useCell, useReactive } from "./src/use-reactive.js"; export { use } from "./src/use-resource.js"; export { useService } from "./src/use-service.js"; export { useSetup } from "./src/use-setup.js"; +export { useStarbeam } from "./src/use-starbeam.js"; export { useDeps, useProp } from "./src/utils.js"; diff --git a/packages/react/react/src/context-provider.ts b/packages/react/react/src/context-provider.ts index f60162cf..1cef576d 100644 --- a/packages/react/react/src/context-provider.ts +++ b/packages/react/react/src/context-provider.ts @@ -13,7 +13,6 @@ export const Starbeam: FunctionComponent = ({ children }) => { const owner = prev ? ReactApp.reactivate(prev) : new ReactApp(); on.cleanup(() => { - console.log({ finalizing: owner }); owner.finalize(); }); diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 4c9c625e..82eab34b 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -1,6 +1,6 @@ import type { browser } from "@domtree/flavors"; import type { Description, Reactive, Tagged } from "@starbeam/interfaces"; -import { RUNTIME, Formula } from "@starbeam/reactive"; +import { Formula, RUNTIME } from "@starbeam/reactive"; import type { IntoResourceBlueprint, Resource } from "@starbeam/resource"; import * as resource from "@starbeam/resource"; import { @@ -235,7 +235,7 @@ export class ReactiveElement implements CleanupTarget { } service = ( - blueprint: IntoResourceBlueprint, + blueprint: IntoResourceBlueprint, description?: string | Description | undefined ): Resource => { const desc = RUNTIME.Desc?.("service", description, "UseSetup.service"); @@ -247,11 +247,11 @@ export class ReactiveElement implements CleanupTarget { CONTEXT.app = ReactApp.instance(context); - return service(blueprint, desc); + return service(blueprint, { description: desc }); }; use = ( - factory: IntoResourceBlueprint, + factory: IntoResourceBlueprint, options?: { initial?: T } ): Reactive => { return internalUseResource( @@ -287,13 +287,12 @@ interface ResourceHost { export function internalUseResource( lifetime: object, - host: ResourceHost>, + host: ResourceHost>, initial: T | undefined ): Reactive { - let unsubscribe: Unsubscribe | undefined = undefined; const resourceCell = Cell(undefined as undefined | Resource); - const create = (blueprint: IntoResourceBlueprint): void => { + const create = (blueprint: IntoResourceBlueprint): void => { resourceCell.set(resource.use(blueprint, { lifetime })); host.notify(); @@ -305,8 +304,7 @@ export function internalUseResource( return (resourceCell.current?.current as T | undefined) ?? initial; }); - unsubscribe = PUBLIC_TIMELINE.on.change(formula, host.notify); - host.on.cleanup(unsubscribe); + host.on.cleanup(PUBLIC_TIMELINE.on.change(formula, host.notify)); return formula; } diff --git a/packages/react/react/src/starbeam/handlers.ts b/packages/react/react/src/starbeam/handlers.ts new file mode 100644 index 00000000..ad209b7e --- /dev/null +++ b/packages/react/react/src/starbeam/handlers.ts @@ -0,0 +1,43 @@ +export interface Handlers { + readonly layout: Set; + readonly idle: Set; + readonly cleanup: Set; +} + +export function Handlers(): Handlers { + return { + layout: new Set(), + cleanup: new Set(), + idle: new Set(), + }; +} + +export function invoke(handlers: Handlers, ...types: (keyof Handlers)[]): void { + for (const type of types) { + for (const callback of handlers[type]) { + callback(); + } + } +} + +export function onHandlers(handlers: () => Handlers): RegisterHandlers { + return { + layout: (callback: () => void) => { + handlers().layout.add(callback); + }, + idle: (callback: () => void) => { + handlers().idle.add(callback); + }, + cleanup: (callback: () => void) => { + handlers().cleanup.add(callback); + }, + }; +} + +export type Callback = () => void; + +export interface RegisterHandlers { + readonly layout: (callback: Callback) => void; + readonly idle: (callback: Callback) => void; + readonly cleanup: (callback: Callback) => void; +} diff --git a/packages/react/react/src/starbeam/instance.ts b/packages/react/react/src/starbeam/instance.ts new file mode 100644 index 00000000..6eb02b95 --- /dev/null +++ b/packages/react/react/src/starbeam/instance.ts @@ -0,0 +1,141 @@ +import type { Reactive } from "@starbeam/interfaces"; +import { CachedFormula, Cell } from "@starbeam/reactive"; +import type { IntoResourceBlueprint, Resource } from "@starbeam/resource"; +import { use as starbeamUse } from "@starbeam/resource"; +import { LIFETIME, PUBLIC_TIMELINE } from "@starbeam/runtime"; +import { service as starbeamService } from "@starbeam/service"; +import type { RegisterLifecycleHandlers } from "@starbeam/use-strict-lifecycle"; +import { isPresent, verified } from "@starbeam/verify"; + +import { missingApp, type ReactApp } from "../context-provider.js"; +import { + type Callback, + Handlers, + invoke, + onHandlers, + type RegisterHandlers, +} from "./handlers.js"; + +export interface StarbeamInstance { + readonly on: RegisterHandlers; + readonly use: UseFn; + readonly service: (resource: IntoResourceBlueprint) => Resource; +} + +export interface InternalStarbeamInstance extends StarbeamInstance { + readonly deactivate: () => void; + readonly reactivate: (lifecycle: Handlers) => InternalStarbeamInstance; +} + +export function activate({ + starbeam, + on, + app, + notify, +}: { + starbeam: InternalStarbeamInstance | undefined; + on: RegisterLifecycleHandlers; + + app: ReactApp | null; + notify: Callback; +}): InternalStarbeamInstance { + const handlers = Handlers(); + const instance = starbeam + ? starbeam.reactivate(handlers) + : StarbeamInstance(handlers, app, notify); + + setup({ on, handlers, instance }); + + return instance; +} + +function setup({ + on, + handlers, + instance, +}: { + on: RegisterLifecycleHandlers; + handlers: Handlers; + instance: InternalStarbeamInstance; +}): void { + on.idle(() => { + invoke(handlers, "idle"); + }); + + on.layout(() => { + invoke(handlers, "layout"); + }); + + on.cleanup(instance.deactivate); +} + +export function StarbeamInstance( + lifecycle: Handlers, + app: ReactApp | null, + notify: Callback +): InternalStarbeamInstance { + let handlers: Handlers | null = lifecycle; + + function service(resource: IntoResourceBlueprint): Resource { + if (!app) missingApp("useStarbeam"); + return starbeamService(resource, { app }); + } + + const use = useFn(() => verified(handlers, isPresent), notify); + + function deactivate() { + if (handlers) { + for (const callback of handlers.cleanup) callback(); + LIFETIME.finalize(handlers); + } + handlers = null; + } + + function reactivate(lifecycle: Handlers): InternalStarbeamInstance { + handlers = lifecycle; + return instance; + } + + const instance = { + on: onHandlers(() => verified(handlers, isPresent)), + use, + service, + deactivate, + reactivate, + } satisfies InternalStarbeamInstance; + + return instance; +} + +type PropagateUndefined = O extends undefined ? undefined : never; + +type UseFn = ( + resource: IntoResourceBlueprint, + options?: O +) => Reactive>; + +function useFn(handlers: () => Handlers, notify: Callback): UseFn { + function use( + resource: IntoResourceBlueprint, + options?: O + ): Reactive> { + const resourceCell = Cell(undefined as Resource | undefined); + + handlers().layout.add(() => { + resourceCell.set(starbeamUse(resource, { lifetime: handlers })); + notify(); + }); + + const formula = CachedFormula( + () => resourceCell.current?.current ?? options?.initial + ); + + handlers().cleanup.add(() => { + PUBLIC_TIMELINE.on.change(formula, notify); + }); + + return formula as Reactive; + } + + return use; +} diff --git a/packages/react/react/src/use-component-instance.ts b/packages/react/react/src/use-component-instance.ts new file mode 100644 index 00000000..36af848c --- /dev/null +++ b/packages/react/react/src/use-component-instance.ts @@ -0,0 +1,25 @@ +import { useState } from "react"; + +/** + * This hook produces a unique instance representing the current React + * component. If it's called multiple times inside a single React component, + * it will return the same instance. + * + * It returns the same instance even in strict mode when the component + * is rendered multiple times. + * + * It doesn't use other Starbeam hooks, since it is used to build those hooks. + */ +export function useComponentInstance(): object { + // we can't use useRef here, since it will produce a different instance + // each time `useComponentInstance` is called, and we want multiple calls + // to return the same instance. The same problem exists with `useState` taking + // a callback or useMemo. + + // We use `useState` to get a unique instance for each component, and then + // we use `useState` to store the instance in a ref. + const [instance] = useState(() => ({})); + const [, setInstance] = useState(instance); + return instance; + +} diff --git a/packages/react/react/src/use-reactive.ts b/packages/react/react/src/use-reactive.ts index f9141b64..5e6daa4c 100644 --- a/packages/react/react/src/use-reactive.ts +++ b/packages/react/react/src/use-reactive.ts @@ -1,11 +1,12 @@ import type { Description, Reactive } from "@starbeam/interfaces"; -import { RUNTIME, Formula as Formula, CachedFormula } from "@starbeam/reactive"; -import { PUBLIC_TIMELINE } from "@starbeam/runtime"; import { - Cell, - LIFETIME, - Wrap, -} from "@starbeam/universal"; + CachedFormula, + Formula as Formula, + isReactive, + RUNTIME, +} from "@starbeam/reactive"; +import { PUBLIC_TIMELINE } from "@starbeam/runtime"; +import { Cell, LIFETIME, Wrap } from "@starbeam/universal"; import { useLifecycle } from "@starbeam/use-strict-lifecycle"; import { useState } from "react"; @@ -23,7 +24,7 @@ import { useSetup } from "./use-setup.js"; */ export function useReactive( - computeFn: () => T, + computeFn: Reactive | (() => T), description?: string | Description | undefined ): T { const desc = RUNTIME.Desc?.("formula", description); @@ -32,11 +33,18 @@ export function useReactive( return useLifecycle({ props: computeFn }).render( ({ on }, originalCompute) => { + if ( + !isReactive(originalCompute) && + typeof originalCompute !== "function" + ) { + console.trace(); + } + let compute = originalCompute; // compute can change, so the `PolledFormula` doesn't close over the original value, but // rather invokes the **current** value (which can change in `on.update`). - const formula = Formula(() => compute(), desc); + const formula = Formula(() => read(compute), desc); on.update((newCompute) => { compute = newCompute; @@ -54,6 +62,10 @@ export function useReactive( ).current; } +function read(value: Reactive | (() => T)): T { + return isReactive(value) ? value.read() : value(); +} + /** * Returns a function that can be called to notify React that the current component should be * re-rendered. diff --git a/packages/react/react/src/use-resource.ts b/packages/react/react/src/use-resource.ts index 29514e2e..8d123ad5 100644 --- a/packages/react/react/src/use-resource.ts +++ b/packages/react/react/src/use-resource.ts @@ -10,14 +10,14 @@ import { internalUseResource } from "./element.js"; import { useNotify } from "./use-reactive.js"; export function use( - factory: IntoResourceBlueprint, + factory: IntoResourceBlueprint, options?: | { initial?: T; description?: string | Description | undefined } | unknown[], dependencies?: unknown[] ): T | undefined { const value = createResource( - factory as IntoResourceBlueprint, + factory as IntoResourceBlueprint, options, dependencies ); @@ -26,7 +26,7 @@ export function use( } function createResource( - factory: IntoResourceBlueprint, + factory: IntoResourceBlueprint, options?: { initial?: T } | unknown[], dependencies?: unknown[] ): Reactive { @@ -48,11 +48,11 @@ function createResource( const { deps, initialValue } = normalize(); - return useLifecycle({ props: factory, validate: deps }).render< - Reactive - >(({ on, validate }, _) => { - validate(sameDeps); - + return useLifecycle({ + props: factory, + validate: deps, + with: sameDeps, + }).render>(({ on }, _) => { const lifetime = {}; const resource = internalUseResource( lifetime, @@ -69,8 +69,8 @@ function createResource( } export function sameDeps( - prev: unknown[] | undefined, - next: unknown[] | undefined + next: unknown[] | undefined, + prev: unknown[] | undefined ): boolean { if (prev === undefined || next === undefined) { return prev === next; diff --git a/packages/react/react/src/use-setup.ts b/packages/react/react/src/use-setup.ts index 566ddcac..d9684e5f 100644 --- a/packages/react/react/src/use-setup.ts +++ b/packages/react/react/src/use-setup.ts @@ -1,5 +1,5 @@ import type { Description, Reactive } from "@starbeam/interfaces"; -import { isReactive, RUNTIME, Formula } from "@starbeam/reactive"; +import { Formula, isReactive, RUNTIME } from "@starbeam/reactive"; import { setupFunction, unsafeTrackedElsewhere, @@ -50,7 +50,7 @@ export function useSetup< const { instance } = useLifecycle({ validate: starbeam, - }).render(({ on, validate }, _, prev) => { + }).render(({ on }, _, prev) => { const element = ReactiveElement.activate( notify, starbeam, @@ -60,8 +60,6 @@ export function useSetup< const instance = setupFunction(() => callback(element)); - validate((nextStarbeam, prevStarbeam) => nextStarbeam === prevStarbeam); - on.layout(() => { ReactiveElement.layout(element); }); diff --git a/packages/react/react/src/use-starbeam.ts b/packages/react/react/src/use-starbeam.ts new file mode 100644 index 00000000..402f1492 --- /dev/null +++ b/packages/react/react/src/use-starbeam.ts @@ -0,0 +1,41 @@ +import { isReactive, type ReadValue } from "@starbeam/reactive"; +import { useLifecycle } from "@starbeam/use-strict-lifecycle"; + +import { useStarbeamApp } from "./context-provider.js"; +import type { + InternalStarbeamInstance, + StarbeamInstance, +} from "./starbeam/instance.js"; +import { activate } from "./starbeam/instance.js"; +import { useReactive } from "./use-reactive.js"; +import { sameDeps } from "./use-resource.js"; + +export function useStarbeam( + callback: (instance: StarbeamInstance) => T, + deps?: unknown[] | undefined +): ReadValue { + const app = useStarbeamApp({ feature: "useStarbeam", allowMissing: true }); + + const instance = useLifecycle({ + props: deps, + validate: deps, + with: sameDeps, + }).render<{ + instance: T; + starbeam: InternalStarbeamInstance; + }>(({ on, notify }, deps, prev) => { + const starbeam = activate({ + starbeam: prev?.starbeam, + on, + app, + notify, + }); + + const instance = callback(starbeam); + return { instance, starbeam }; + }).instance; + + return isReactive(instance) + ? (useReactive(instance) as ReadValue) + : (instance as ReadValue); +} diff --git a/packages/react/react/tests/use-reactive.spec.ts b/packages/react/react/tests/use-reactive.spec.ts index f50fb44d..90daeed7 100644 --- a/packages/react/react/tests/use-reactive.spec.ts +++ b/packages/react/react/tests/use-reactive.spec.ts @@ -230,17 +230,12 @@ describe("useReactive", () => { }).compute(); }); - console.log("initial"); expect(result.value).toEqual({ starbeam: 0, react: 0 }); - console.log("clicking starbeam"); await result.findByText("++Starbeam++").fire.click(); - console.log("clicked starbeam"); expect(result.value).toEqual({ starbeam: 1, react: 0 }); - console.log("clicked react"); await result.findByText("++React++").fire.click(); - console.log("clicked react"); expect(result.value).toEqual({ starbeam: 1, react: 1 }); } ); diff --git a/packages/react/react/tests/use-service.spec.ts b/packages/react/react/tests/use-service.spec.ts index f4bb702a..4ff83424 100644 --- a/packages/react/react/tests/use-service.spec.ts +++ b/packages/react/react/tests/use-service.spec.ts @@ -112,7 +112,6 @@ const CurrentUser = Resource((r) => { const lastMessage = Cell(null as Auth | null, "last message"); const c = AUTH_CHANNELS.subscribe("auth"); - console.log({ c, latest: AUTH_CHANNELS.latest() }); c.onMessage((message) => { lastMessage.set(message); diff --git a/packages/react/react/tests/use-starbeam-app.spec.ts b/packages/react/react/tests/use-starbeam-app.spec.ts new file mode 100644 index 00000000..c09d171b --- /dev/null +++ b/packages/react/react/tests/use-starbeam-app.spec.ts @@ -0,0 +1,63 @@ +// @vitest-environment jsdom + +import { type ReactApp, Starbeam, useStarbeamApp } from "@starbeam/react"; +import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; +import { describe, expect } from "@starbeam-workspace/test-utils"; +import { + createElement, + type Dispatch, + type SetStateAction, + useState, +} from "react"; + +describe("useStarbeamApp", () => { + testReact( + "useStarbeamApp maintains a stable instance", + async (root) => { + let currentApp: ReactApp | null = null; + + const result = await root + .expectStable() + .expectHTML((counter) => ``) + .render((state) => { + const [counter, setCounter] = useState(0); + state.value(counter); + return createElement( + Starbeam, + null, + react.render(Child, { counter, setCounter }) + ); + }); + + function Child(props: { + counter: number; + setCounter: Dispatch>; + }) { + currentApp = useStarbeamApp({ feature: "test" }); + return html.button( + { + onClick: () => { + props.setCounter((i) => i + 1); + }, + }, + String(props.counter) + ); + } + + expect(currentApp).not.toBeNull(); + + { + const lastApp = currentApp; + await result.rerender(); + expect(currentApp).toBe(lastApp); + } + + { + const lastApp = currentApp; + await result.find("button").fire.click(); + expect(result.value).toBe(1); + expect(currentApp).toBe(lastApp); + } + } + ); +}); diff --git a/packages/react/react/tests/use-starbeam.spec.ts b/packages/react/react/tests/use-starbeam.spec.ts new file mode 100644 index 00000000..7b41d558 --- /dev/null +++ b/packages/react/react/tests/use-starbeam.spec.ts @@ -0,0 +1,84 @@ +// @vitest-environment jsdom + +import { Starbeam, useStarbeam } from "@starbeam/react"; +import { Cell, Formula } from "@starbeam/reactive"; +import { Resource } from "@starbeam/resource"; +import type { RenderState } from "@starbeam-workspace/react-test-utils"; +import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; +import { describe, expect } from "@starbeam-workspace/test-utils"; +import { createElement } from "react"; + +Error.stackTraceLimit = Infinity; + +describe("useStarbeam", () => { + const testResource = Resource(({ on }) => { + const cell = Cell(0); + + on.cleanup(() => { + cell.current = -1; + }); + + return { + get count() { + return cell.current; + }, + increment() { + cell.set(cell.current + 1); + }, + }; + }); + + interface TestState { + count: number; + increment: () => void; + } + + testReact("using a resource", async (root) => { + const result = await root + .expectHTML((value) => `${value?.count ?? "uninitialized"}`) + .render((state) => { + return useStarbeam(({ use }) => { + const resource = use(testResource); + + return Formula(() => { + console.log({ resource, current: resource.current }); + state.value(resource.current); + return html.span(resource.current?.count ?? "uninitialized"); + }); + }); + }); + + await result.rerender(); + expect(result.value?.count).toBe(0); + + await result.act(() => result.value?.increment()); + expect(result.value?.count).toBe(1); + }); + + testReact("using a service", async (root) => { + const result = await root + .expectHTML((value) => `${value?.count ?? "uninitialized"}`) + .render((state) => { + console.log("inside Starbeam frame"); + return createElement(Starbeam, null, react.render(App, { state })); + }); + + function App({ state }: { state: RenderState }) { + return useStarbeam(({ service }) => { + const resource = service(testResource); + + return Formula(() => { + console.log({ resource: resource.current?.count }); + state.value(resource.current); + return html.span(resource.current?.count ?? "uninitialized"); + }); + }); + } + + await result.rerender(); + expect(result.value?.count).toBe(0); + + await result.act(() => result.value?.increment()); + expect(result.value?.count).toBe(1); + }); +}); diff --git a/packages/react/test-utils/src/modes.ts b/packages/react/test-utils/src/modes.ts index 4654f878..d14a6e5a 100644 --- a/packages/react/test-utils/src/modes.ts +++ b/packages/react/test-utils/src/modes.ts @@ -276,6 +276,7 @@ export class SetupTestRoot { } expectHTML(expectHtml: (value: T, props: Props) => string): this { + if (this.#expectStable === undefined) this.#expectStable = (value) => value; this.#expectHtml = expectHtml; return this; } diff --git a/packages/react/use-strict-lifecycle/index.ts b/packages/react/use-strict-lifecycle/index.ts index 1248230e..81f79a4c 100644 --- a/packages/react/use-strict-lifecycle/index.ts +++ b/packages/react/use-strict-lifecycle/index.ts @@ -5,6 +5,7 @@ export { endReadonly as unmaskRendering, unsafeTrackedElsewhere, } from "./src/react.js"; +export type { RegisterLifecycleHandlers } from "./src/resource.js"; export { useLifecycle } from "./src/resource.js"; export { type Ref, diff --git a/packages/react/use-strict-lifecycle/src/resource.ts b/packages/react/use-strict-lifecycle/src/resource.ts index cbbc64fe..ccb0f243 100644 --- a/packages/react/use-strict-lifecycle/src/resource.ts +++ b/packages/react/use-strict-lifecycle/src/resource.ts @@ -119,32 +119,51 @@ type UseLifecycleBuilder = ( args: A, prev?: T | undefined ) => T; -type Validator
    = (args: A, prev: A) => boolean; - -export function useLifecycle({ - props, - validate, -}: { - props?: A; - validate?: V; -} = {}): { +type Validator = (args: V, prev: V) => boolean; + +interface Options { + readonly props?: A | undefined; + readonly validate?: V; + readonly with?: Validator; +} + +export function useLifecycle( + options: Options = {} +): { render: (build: UseLifecycleBuilder) => T; } { + const { props } = options; + let validateWith: Validator | undefined; + let validate: V | undefined; + + if ("validate" in options) { + validate = options.validate; + validateWith = options.with ?? Object.is; + } + return { - render: (build: UseLifecycleBuilder) => { + render: ((build: UseLifecycleBuilder) => { const [, setNotify] = useState({}); + const notify = () => { + setNotify({}); + }; const state = useRef("mounting"); - const initialRef = useRef>( - UNINITIALIZED - ); + const initialRef = useRef< + UNINITIALIZED | ResourceInstance + >(UNINITIALIZED); if (initialRef.current === UNINITIALIZED) { - initialRef.current = ResourceBuilder.build(build, props as A); + initialRef.current = ResourceBuilder.build({ + build, + notify, + validateWith, + args: props, + }); } else { if (state.current === "mounted") { // If we're already mounted, that means we're updating, so call the update callback. - initialRef.current.run("update", props as A); + initialRef.current.run("update", props); } else { // If we're remounting, we're effectively in the initial state, and the work already happened // in `useLayoutEffect`, so don't do anything here. @@ -152,19 +171,20 @@ export function useLifecycle({ } } - const ref = initialRef as MutableRefObject>; + const ref = initialRef as MutableRefObject< + ResourceInstance + >; // The callback to useLayoutEffect is created once, but should see the most recent rendered args. - const { ref: renderedArgs } = useLastRenderRef(props as A); + const { ref: renderedArgs } = useLastRenderRef(props); - const { ref: currentValidate, prev: prevValidate } = useLastRenderRef( - validate as V - ); + const { ref: currentValidate, prev: prevValidate } = + useLastRenderRef(validate); if (prevValidate !== UNINITIALIZED) { const isValid = ref.current.validate( - currentValidate.current, - prevValidate + currentValidate.current as never, + prevValidate as never ); if (!isValid) { @@ -178,7 +198,7 @@ export function useLifecycle({ useLayoutEffect(() => { switch (state.current) { case "unmounted": { - setNotify({}); + notify(); ref.current = ref.current.remount(renderedArgs.current); state.current = "remounting"; @@ -204,7 +224,7 @@ export function useLifecycle({ }, []); return ref.current.instance; - }, + }) as (build: unknown) => T, }; } @@ -234,14 +254,31 @@ class ResourceInstance { } } +export interface RegisterLifecycleHandlers { + cleanup: (cleanup: (args: A) => void) => void; + update: (update: (args: A) => void) => void; + layout: (onLayout: (args: A) => void) => void; + idle: (onIdle: (args: A) => void) => void; +} + class ResourceBuilder { - static build( - build: UseLifecycleBuilder, - args: A, - prev?: T | undefined - ): ResourceInstance { + static build({ + build, + notify, + args, + validateWith, + prev, + }: { + build: UseLifecycleBuilder; + notify: () => void; + args: A; + validateWith: Validator | undefined; + prev?: T | undefined; + }): ResourceInstance { const builder = new ResourceBuilder( - build as UseLifecycleBuilder + build as UseLifecycleBuilder, + validateWith, + notify ); beginReadonly(); try { @@ -262,11 +299,13 @@ class ResourceBuilder { args: A, prev: T ): ResourceInstance { - return ResourceBuilder.build( - builder.#build as UseLifecycleBuilder, + return ResourceBuilder.build({ + build: builder.#build as UseLifecycleBuilder, + validateWith: builder.#validateWith, + notify: builder.notify, args, - prev - ); + prev, + }); } static run( @@ -284,15 +323,15 @@ class ResourceBuilder { current: V, prev: V ): boolean { - if (resource.#validator === undefined) { + if (resource.#validateWith === undefined) { return true; } - return resource.#validator(current, prev); + return resource.#validateWith(current, prev); } - #build: UseLifecycleBuilder; - #validator: Validator | undefined = undefined; + readonly #build: UseLifecycleBuilder; + readonly #validateWith: Validator | undefined; #on = { cleanup: new Set<(args: A) => void>(), @@ -301,11 +340,9 @@ class ResourceBuilder { update: new Set<(args: A) => void>(), }; - validate = (validator: Validator): void => { - this.#validator = validator; - }; + readonly notify: () => void; - on = { + readonly on: RegisterLifecycleHandlers = { cleanup: (cleanup: (args: A) => void): void => { this.#on.cleanup.add(cleanup); }, @@ -323,7 +360,13 @@ class ResourceBuilder { }, }; - constructor(build: UseLifecycleBuilder) { + constructor( + build: UseLifecycleBuilder, + validator: Validator | undefined, + notify: () => void + ) { this.#build = build; + this.#validateWith = validator; + this.notify = notify; } } diff --git a/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts b/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts index 30ab63ac..21f4d5b4 100644 --- a/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts @@ -39,7 +39,7 @@ testReact("useResource", async (root) => { }; }); - useLifecycle(undefined).render((lifecycle) => { + useLifecycle().render((lifecycle) => { expect(isRendering()).toBe(true); lifecycle.on.update(() => { diff --git a/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts b/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts index af16d528..af4d871b 100644 --- a/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts @@ -277,28 +277,23 @@ testReact( const lifecycle = useLifecycle({ props: count, validate: cleanup, - }).render( - ({ on, validate }, count, prev?: State | undefined): State => { - const object = { count, cleanup: prev?.cleanup ?? 0 }; - - on.cleanup((newCount) => { - object.count = newCount; - object.cleanup++; - }); + with: Object.is, + }).render(({ on }, count, prev?: State | undefined): State => { + const object = { count, cleanup: prev?.cleanup ?? 0 }; - on.update((newCount) => { - object.count = newCount; - }); + on.cleanup((newCount) => { + object.count = newCount; + object.cleanup++; + }); - validate((newCleanup, oldCleanup) => { - return newCleanup === oldCleanup; - }); + on.update((newCount) => { + object.count = newCount; + }); - setup.value(object); + setup.value(object); - return object; - } - ); + return object; + }); return react.fragment( html.div(lifecycle.count), diff --git a/packages/universal/debug/src/call-stack/debug/module.ts b/packages/universal/debug/src/call-stack/debug/module.ts index aeb6b42a..71b9466e 100644 --- a/packages/universal/debug/src/call-stack/debug/module.ts +++ b/packages/universal/debug/src/call-stack/debug/module.ts @@ -39,7 +39,6 @@ export function normalizeModule( if (codebase) { const { prefix, suffix } = pivotPath(codebase, path); - console.log({ codebase, path, prefix, suffix }); return { root: prefix, path: stripLeadingSlash(suffix), diff --git a/packages/universal/debug/src/description/debug/description.ts b/packages/universal/debug/src/description/debug/description.ts index a7abc9de..9a0fbf9f 100644 --- a/packages/universal/debug/src/description/debug/description.ts +++ b/packages/universal/debug/src/description/debug/description.ts @@ -147,6 +147,5 @@ export const Desc = (( specified, caller, }); - console.log({ desc: { ...desc } }); return desc; }) satisfies DescriptionRuntime; diff --git a/packages/universal/resource/src/api.ts b/packages/universal/resource/src/api.ts index 1adb5008..44d3d55b 100644 --- a/packages/universal/resource/src/api.ts +++ b/packages/universal/resource/src/api.ts @@ -1,4 +1,4 @@ -import type { Description, Reactive } from "@starbeam/interfaces"; +import type { Description } from "@starbeam/interfaces"; import type { FormulaFn, ReadValue } from "@starbeam/reactive"; import { ResourceBlueprintImpl, type UseOptions } from "./resource.js"; @@ -36,10 +36,10 @@ export const Resource = ResourceBlueprintImpl.create; export { isResource } from "./resource.js"; export type ResourceBlueprint = - | ResourceBlueprintImpl, void> + | ResourceBlueprintImpl | ResourceBlueprintImpl; -export type IntoResourceBlueprint = +export type IntoResourceBlueprint = | ResourceBlueprint | ResourceConstructor; diff --git a/packages/universal/runtime/src/context/context.ts b/packages/universal/runtime/src/context/context.ts index 4faabb86..ae206108 100644 --- a/packages/universal/runtime/src/context/context.ts +++ b/packages/universal/runtime/src/context/context.ts @@ -34,16 +34,19 @@ export class AppContext { return this.#app !== undefined; } - create( + create( key: object, - constructor: (...args: Args) => Ret, - ...args: Args + constructor: () => Ret, + { + app, + }: { + app?: object | undefined; + } = {} ): Ret { - return this.#appSingletons.create(key, constructor, ...args); + return this.#appSingletons(app).create(key, constructor); } - get #appSingletons(): SingletonContext { - const app = this.app; + #appSingletons(app: object | undefined = this.app): SingletonContext { let singletons = this.#singletons.get(app); if (singletons === undefined) { @@ -58,19 +61,15 @@ export class AppContext { class SingletonContext { #instances = new WeakMap(); - create( - key: object | undefined, - constructor: (...args: Args) => Ret, - ...args: Args - ): Ret { + create(key: object | undefined, constructor: () => Ret): Ret { if (key === undefined) { - return constructor(...args); + return constructor(); } let existing = this.#instances.get(key) as Ret | undefined; if (existing === undefined) { - existing = constructor(...args); + existing = constructor(); this.#instances.set(key, existing as object); } diff --git a/packages/universal/runtime/tests/protocol.spec.ts b/packages/universal/runtime/tests/protocol.spec.ts index 27dcc303..183a26c7 100644 --- a/packages/universal/runtime/tests/protocol.spec.ts +++ b/packages/universal/runtime/tests/protocol.spec.ts @@ -45,11 +45,8 @@ describe("Tagged", () => { expect(String(PUBLIC_TIMELINE.now)).not.toBe(String(original)); - console.log("reading", PUBLIC_TIMELINE.now); tom.read(); - console.log("writing", PUBLIC_TIMELINE.now); tom.current = "Tom Dale"; - console.log("wrote", PUBLIC_TIMELINE.now); expect(String(PUBLIC_TIMELINE.now), "PUBLIC_TIMELINE.now").not.toBe( String(original) ); diff --git a/packages/universal/service/src/service.ts b/packages/universal/service/src/service.ts index 716fa56d..b16766f0 100644 --- a/packages/universal/service/src/service.ts +++ b/packages/universal/service/src/service.ts @@ -6,11 +6,20 @@ import { CONTEXT } from "@starbeam/runtime"; type Blueprint = IntoResourceBlueprint; +/** + * The `Service` function takes a resource blueprint and turns it into a + * service: a resource that is created once and then shared across all + * components rendered within a given app instance.s + */ export function Service( blueprint: Blueprint, - description?: string | Description + { + description, + app = CONTEXT.app, + }: { description?: string | Description | undefined; app?: object } = {} ): ResourceBlueprint { return Resource(({ use }) => { + CONTEXT.app = app; return CONTEXT.create(blueprint, () => { return use(blueprint); }); @@ -19,9 +28,16 @@ export function Service( export function service( resource: Blueprint, - description?: string | Description + { + description, + app = CONTEXT.app, + }: { description?: string | Description | undefined; app?: object } = {} ): Resource { - return use(Service(resource, RUNTIME.Desc?.("service", description)), { - lifetime: CONTEXT.app, - }); + return use( + Service(resource, { + description: RUNTIME.Desc?.("service", description), + app, + }), + { lifetime: app } + ); } diff --git a/packages/universal/verify/index.ts b/packages/universal/verify/index.ts index 8cdc56b9..aed1711d 100644 --- a/packages/universal/verify/index.ts +++ b/packages/universal/verify/index.ts @@ -1,3 +1,9 @@ +import { + verified as verifiedDev, + verify as verifyDev, + type VerifyFn, +} from "./src/verify.js"; + export { exhaustive, hasItems, @@ -10,18 +16,12 @@ export { isWeakKey, } from "./src/assertions/basic.js"; export { isOneOf } from "./src/assertions/multi.js"; -export { type TypeOf, hasType } from "./src/assertions/types.js"; +export { hasType, type TypeOf } from "./src/assertions/types.js"; export { type Expectation, expected, VerificationError } from "./src/verify.js"; -import { - type VerifyFn, - verified as verifiedDev, - verify as verifyDev, -} from "./src/verify.js"; - export const verify: VerifyFn = import.meta.env.DEV ? verifyDev : verifyDev.noop; -export const verified: typeof verifiedDev["noop"] = import.meta.env.DEV +export const verified: (typeof verifiedDev)["noop"] = import.meta.env.DEV ? verifiedDev : verifiedDev.noop; diff --git a/packages/universal/verify/src/verify.ts b/packages/universal/verify/src/verify.ts index de7c3ac4..15cebee5 100644 --- a/packages/universal/verify/src/verify.ts +++ b/packages/universal/verify/src/verify.ts @@ -4,13 +4,9 @@ export class VerificationError extends Error { } } -export type VerifyFn = ( - value: Value, - check: (input: Input) => input is Output, - error?: Expectation -) => asserts value is Output & Value; +export type VerifyFn = typeof verify; -export function verify( +export function verify( value: Value, check: (input: Input) => input is Output, error?: Expectation @@ -19,7 +15,12 @@ export function verify( value: Value, check: (input: Value) => input is Narrow, error?: Expectation -): asserts value is Narrow { +): asserts value is Narrow; +export function verify( + value: unknown, + check: (input: unknown) => boolean, + error?: Expectation +): void { if (!check(value)) { const associated = ASSOCIATED.get(check); const expectation = Expectation.merge(associated, error); @@ -40,21 +41,11 @@ verify.noop = (() => { /** noop */ }) as unknown as Exclude; -function noop( - value: Value, - check: (input: Input) => input is Output, - error?: Expectation -): void; -function noop( - value: Value, - check: (input: Input) => input is Output, - error?: Expectation -): asserts value is Output & Value; function noop(): void { return; } -verify.noop = noop; +verify.noop = noop as unknown as VerifyFn; export function verified( value: T, From af86b0823a35953f9c20be515624ef3ae2f9f9aa Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 10 Apr 2023 00:16:39 -0700 Subject: [PATCH 33/46] Finish useStrictLifecycle Cleanup --- packages/react/use-strict-lifecycle/index.ts | 10 +- .../react/use-strict-lifecycle/src/checker.ts | 11 - .../use-strict-lifecycle/src/lifecycle.ts | 336 ++++++++++++++++ .../use-strict-lifecycle/src/overload.ts | 89 ----- .../use-strict-lifecycle/src/resource.ts | 372 ------------------ .../use-strict-lifecycle/src/updating-ref.ts | 97 +---- .../react/use-strict-lifecycle/src/utils.ts | 80 ++-- .../tests/updating-ref.spec.ts | 37 -- 8 files changed, 407 insertions(+), 625 deletions(-) delete mode 100644 packages/react/use-strict-lifecycle/src/checker.ts create mode 100644 packages/react/use-strict-lifecycle/src/lifecycle.ts delete mode 100644 packages/react/use-strict-lifecycle/src/overload.ts delete mode 100644 packages/react/use-strict-lifecycle/src/resource.ts diff --git a/packages/react/use-strict-lifecycle/index.ts b/packages/react/use-strict-lifecycle/index.ts index 81f79a4c..941229af 100644 --- a/packages/react/use-strict-lifecycle/index.ts +++ b/packages/react/use-strict-lifecycle/index.ts @@ -1,3 +1,5 @@ +export type { RegisterLifecycleHandlers } from "./src/lifecycle.js"; +export { useLifecycle } from "./src/lifecycle.js"; export { isRestrictedRead as isRendering } from "./src/react.js"; export { beginReadonly as maskRendering, @@ -5,10 +7,4 @@ export { endReadonly as unmaskRendering, unsafeTrackedElsewhere, } from "./src/react.js"; -export type { RegisterLifecycleHandlers } from "./src/resource.js"; -export { useLifecycle } from "./src/resource.js"; -export { - type Ref, - useUpdatingRef, - useUpdatingVariable, -} from "./src/updating-ref.js"; +export { type Ref, useLastRenderRef } from "./src/updating-ref.js"; diff --git a/packages/react/use-strict-lifecycle/src/checker.ts b/packages/react/use-strict-lifecycle/src/checker.ts deleted file mode 100644 index 9d6a93e9..00000000 --- a/packages/react/use-strict-lifecycle/src/checker.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Overload } from "./overload.js"; -import type { AdHocCheck, Check } from "./utils.js"; - -export function checker( - assertion: [Check] | AdHocCheck -): Check { - return Overload>().resolve(assertion, { - 1: (arg) => arg, - 2: (test, failure) => ({ test, failure }), - }); -} diff --git a/packages/react/use-strict-lifecycle/src/lifecycle.ts b/packages/react/use-strict-lifecycle/src/lifecycle.ts new file mode 100644 index 00000000..2393af07 --- /dev/null +++ b/packages/react/use-strict-lifecycle/src/lifecycle.ts @@ -0,0 +1,336 @@ +/** + * # High Level Documentation + * + * When you render a component in React, it gets a unique "rendered component + * instance". If the component function contains any calls to `useState`, + * `useRef`, etc. they will be associated with that unique instance. + * + * Consider this example: + * + * ```ts + * function Counter() { + * const [count, setCount] = useState(0); + * + * return <> + * + *

    {count}

    + * + * } + * ``` + * + * When React render the Counter component for the first time, the component + * calls `useState(0)`. React creates a fresh place to store state **for this + * rendered component instance** and stores `0` in it. + * + * The call to `useState(0)` returns the number `0` as well as a function that + * you can use to update the counter value. + * + * Whenever React runs the Counter function a second time **for the same + * component instance**, the call to `useState` links back up to the same + * storage location, and React returns the current value stored in that + * location, as well as the setter function. + * + * When you use the setter returned by `useState` to increment the value, React + * changes the value in the storage location (in this case to `1`). Since a + * storage location **associated with this component instance** changed, React + * knows it needs to re-render the `Counter` component, and it schedules an + * update. + * + * The next time React renders the component, the call to `useState` will link + * back up to the storage location, and voila, the return value will be `[1, + * setter]`. + * + * ## The Catch + * + * This all works great, with a small catch. + * + * As of React 18, React may run a component's cleanup functions (the return + * values of `useEffect` and `useLayoutEffect`) and *then* run its setup + * functions (the callbacks in `useEffect` and `useLayoutEffect`) *again*. + * + * > This currently happens when using [Fast Refresh] and is enforced via React + * > 18 strict mode. The React team has said that it may run setup functions + * > after cleanup for other reasons in the future. For now, support for strict + * > mode is a good enough reason to care. + * + * This means that a "component instance" may persist across cleanup. + * **Importantly**, this means that your setup code is not allowed to assume + * that it runs **after** the top-level of your component function, but + * **before** cleanup. + * + * > TODO: Add an example + * + * This is all rather hard to get right. + * + * ## The Solution + * + * The `useLifecycle` hook gives you a way to create a new instance of something + * when the component is first instantiated, clean it up when the component is + * unmounted, and create a brand **new** instance when the component is + * reactivated. + * + * TL;DR It works almost the same way that per-component state in React works, + * but gives you a fresh copy whenever React re-attaches the component. + * + * In practice, this means that you can treat React's behavior as a pooling + * optimization, rather than as a detail that your component needs to think + * about. + * + * ## Lifecycle + * + * ``` + * first run: instantiating + * - inline: create + * - before paint: attach + * - browser idle: ready + * + * second run: updating + * - inline: update + * + * unmounting + * - inline: finalize instance & unmount + * + * remounting (same as mounting) + * - inline: create + * - before paint: attach + * - browser idle: ready + * ... + * ``` + * + * [fast refresh]: https://www.npmjs.com/package/react-refresh + */ + +import { useEffect, useLayoutEffect, useRef, useState } from "react"; + +import { beginReadonly, endReadonly } from "./react.js"; +import { + type Ref, + useInitializedRef, + useLastRenderRef, +} from "./updating-ref.js"; +import { checked, isInitialized, mapEntries, UNINITIALIZED } from "./utils.js"; + +enum State { + /** + * A component starts out in the "mounting" state and transitions to the + * "mounted" state in the component's first `useLayoutEffect` callback. + */ + mounting = "mounting", + /** + * Once a component has reached its first `useLayoutEffect` callback, it's + * in the "mounted" state until it's unmounted. + */ + mounted = "mounted", + /** + * A component is in the "unmounted" when its `useLayoutEffect` cleanup + * function runs. + */ + unmounted = "unmounted", + /** + * If a component's `useLayoutEffect` function runs again, it's in the + * "remounting" state. + */ + remounting = "remounting", +} + +type UseLifecycleBuilder = ( + builder: Builder
    , + args: A, + prev?: T | undefined +) => T; +type Validator = (args: V, prev: V) => boolean; + +interface Options { + readonly props?: A | undefined; + readonly validate?: V; + readonly with?: Validator; +} + +enum LifecycleEvent { + cleanup = "cleanup", + layout = "layout", + idle = "idle", + update = "update", +} + +export function useLifecycle( + options: Options = {} +): { + render: (build: UseLifecycleBuilder) => T; +} { + return { + render: ((build: UseLifecycleBuilder) => { + const [, setNotify] = useState({}); + const notify = () => { + setNotify({}); + }; + const state = useRef(State.mounting); + const [renderedArgs] = useLastRenderRef(options.props as A); + + const [instance, isUpdate] = useInitializedRef(() => { + return buildInstance({ + options: { + build, + args: renderedArgs, + notify, + validateWith: options.with ?? Object.is, + }, + }); + }); + + if (isUpdate) { + if (state.current === State.mounted) { + // If already mounted, we're _updating_: call the update callback. + run(LifecycleEvent.update); + } else { + // If _remounting_, update already happened in `useLayoutEffect`. + state.current = State.mounted; + } + } + + function run(event: LifecycleEvent): void { + runHandlers(checked(instance.current, isInitialized), event); + } + + const [validate, prev] = useLastRenderRef(options.validate); + + if (prev !== UNINITIALIZED) { + const isValid = validateUpdate( + instance.current.options.validateWith, + validate.current as V, + prev as V + ); + + // If validation fails, immediately remount. + if (!isValid) { + run(LifecycleEvent.cleanup); + instance.current = buildInstance(instance.current); + run(LifecycleEvent.layout); + } + } + + useLayoutEffect(() => { + if (state.current === State.unmounted) { + // Remount: + // Notify react so that remounting causes a re-render. + notify(); + // Rebuild the instance. + instance.current = buildInstance( + checked(instance.current, isInitialized) + ); + + // Finish the job in the top-level render. This maintains timing + // consistency with the initial render (the instantiation callback + // always runs during a render). + state.current = State.remounting; + } else { + // Initial Mount: + state.current = State.mounted; + } + + run(LifecycleEvent.layout); + + return () => { + run(LifecycleEvent.cleanup); + state.current = State.unmounted; + }; + }, []); + + useEffect(() => { + run(LifecycleEvent.idle); + + // we don't need to return a cleanup function since we already did that in useLayoutEffect + }, []); + + return instance.current.value; + }) as (build: unknown) => T, + }; +} + +interface Instance { + readonly value: T; + readonly options: LifecycleOptions; + readonly handlers: HandlerSets; +} + +type HandlerSets = { + readonly [K in LifecycleEvent]: Set<(args: A) => void>; +}; + +export type RegisterLifecycleHandlers = { + readonly [K in LifecycleEvent]: (handler: (args: A) => void) => void; +}; + +interface LifecycleOptions { + readonly build: UseLifecycleBuilder; + readonly args: Ref; + readonly validateWith: Validator | undefined; + readonly notify: () => void; +} + +interface LifecycleState { + readonly options: LifecycleOptions; + readonly handlers: HandlerSets; +} + +function buildInstance({ + options, + value: prev, +}: { + options: LifecycleOptions; + value?: T; +}): Instance { + const handlers: HandlerSets = { + cleanup: new Set(), + layout: new Set(), + idle: new Set(), + update: new Set(), + }; + const args = options.args; + const builder = Builder({ options, handlers }); + beginReadonly(); + try { + const instance: Instance = { + value: options.build(builder, args.current, prev), + handlers, + options, + }; + endReadonly(); + return instance; + } catch (e) { + endReadonly(); + throw e; + } +} + +const runHandlers = ( + instance: { handlers: HandlerSets; options: { args: Ref } }, + event: LifecycleEvent +): void => { + for (const callback of instance.handlers[event]) { + callback(instance.options.args.current); + } +}; + +const validateUpdate = ( + validateWith: Validator | undefined, + current: V, + prev: V +): boolean => validateWith === undefined || validateWith(current, prev); + +export interface Builder { + readonly notify: () => void; + readonly on: RegisterLifecycleHandlers; +} + +const Builder = (state: LifecycleState): Builder => { + return { + notify: state.options.notify, + on: mapEntries(LifecycleEvent, (value) => registerFn(state, value)), + }; +}; + +const registerFn = + (state: { handlers: HandlerSets }, handler: LifecycleEvent) => + (callback: (args: A) => void) => + state.handlers[handler].add(callback); diff --git a/packages/react/use-strict-lifecycle/src/overload.ts b/packages/react/use-strict-lifecycle/src/overload.ts deleted file mode 100644 index 004f9590..00000000 --- a/packages/react/use-strict-lifecycle/src/overload.ts +++ /dev/null @@ -1,89 +0,0 @@ -type Matcher< - In extends readonly unknown[], - Out, - Unhandled extends number -> = Unhandled extends infer K - ? K extends number - ? { [P in K]: (...args: Extract) => Out } - : never - : never; - -export function Overload(): { - of: (input: In) => OverloadImpl; - resolve: ( - input: In, - matcher: Matcher - ) => Out; -} { - return { - of: (input: In) => - new OverloadImpl(input, undefined), - resolve: ( - input: In, - matcher: Matcher - ) => { - return new OverloadImpl(input, matcher).resolve( - matcher - ); - }, - }; -} - -class OverloadImpl< - In extends readonly unknown[], - Out, - Unhandled extends number -> { - static of( - args: In - ): OverloadImpl { - return new OverloadImpl(args, undefined); - } - - readonly #args: In; - readonly #matcher: Record | undefined; - - constructor(args: In, matcher: Record | undefined) { - this.#args = args; - this.#matcher = matcher; - } - - #match(orElse?: (...args: unknown[]) => Out): Out { - const match = this.#matcher?.[this.#args.length] as - | ((...args: unknown[]) => readonly unknown[]) - | undefined; - if (match) { - return match(...this.#args) as Out; - } else if (orElse) { - return orElse(...this.#args); - } else { - throw new Error(`no match for ${this.#args.length} arguments`); - } - } - - resolve(this: OverloadImpl): Out; - resolve( - this: OverloadImpl, - matcher: Matcher - ): Out; - resolve(matcher?: Matcher): Out { - if (matcher) { - return this.match(matcher).resolve(); - } - return this.#match(); - } - - else(orElse: (...args: Extract) => Out): Out { - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return - return this.#match(orElse as any) as any; - } - - match>( - match: H - ): OverloadImpl> { - return new OverloadImpl(this.#args, { - ...this.#matcher, - ...match, - }); - } -} diff --git a/packages/react/use-strict-lifecycle/src/resource.ts b/packages/react/use-strict-lifecycle/src/resource.ts deleted file mode 100644 index ccb0f243..00000000 --- a/packages/react/use-strict-lifecycle/src/resource.ts +++ /dev/null @@ -1,372 +0,0 @@ -/** - * # High Level Documentation - * - * When you render a component in React, it gets a unique "rendered component - * instance". If the component function contains any calls to `useState`, - * `useRef`, etc. they will be associated with that unique instance. - * - * Consider this example: - * - * ```ts - * function Counter() { - * const [count, setCount] = useState(0); - * - * return <> - * - *

    {count}

    - * - * } - * ``` - * - * When React render the Counter component for the first time, the component - * calls `useState(0)`. React creates a fresh place to store state **for this - * rendered component instance** and stores `0` in it. - * - * The call to `useState(0)` returns the number `0` as well as a function that - * you can use to update the counter value. - * - * Whenever React runs the Counter function a second time **for the same - * component instance**, the call to `useState` links back up to the same - * storage location, and React returns the current value stored in that - * location, as well as the setter function. - * - * When you use the setter returned by `useState` to increment the value, React - * changes the value in the storage location (in this case to `1`). Since a - * storage location **associated with this component instance** changed, React - * knows it needs to re-render the `Counter` component, and it schedules an - * update. - * - * The next time React renders the component, the call to `useState` will link - * back up to the storage location, and voila, the return value will be `[1, - * setter]`. - * - * ## The Catch - * - * This all works great, with a small catch. - * - * As of React 18, React may run a component's cleanup functions (the return - * values of `useEffect` and `useLayoutEffect`) and *then* run its setup - * functions (the callbacks in `useEffect` and `useLayoutEffect`) *again*. - * - * > This currently happens when using [Fast Refresh] and is enforced via React - * > 18 strict mode. The React team has said that it may run setup functions - * > after cleanup for other reasons in the future. For now, support for strict - * > mode is a good enough reason to care. - * - * This means that a "component instance" may persist across cleanup. - * **Importantly**, this means that your setup code is not allowed to assume - * that it runs **after** the top-level of your component function, but - * **before** cleanup. - * - * > TODO: Add an example - * - * This is all rather hard to get right. - * - * ## The Solution - * - * The `useLifecycle` hook gives you a way to create a new instance of something - * when the component is first instantiated, clean it up when the component is - * unmounted, and create a brand **new** instance when the component is - * reactivated. - * - * TL;DR It works almost the same way that per-component state in React works, - * but gives you a fresh copy whenever React re-attaches the component. - * - * In practice, this means that you can treat React's behavior as a pooling - * optimization, rather than as a detail that your component needs to think - * about. - * - * ## Lifecycle - * - * ``` - * first run: instantiating - * - inline: create - * - before paint: attach - * - browser idle: ready - * - * second run: updating - * - inline: update - * - * unmounting - * - inline: finalize instance & unmount - * - * remounting (same as mounting) - * - inline: create - * - before paint: attach - * - browser idle: ready - * ... - * ``` - * - * [fast refresh]: https://www.npmjs.com/package/react-refresh - */ - -import { - type MutableRefObject, - useEffect, - useLayoutEffect, - useRef, - useState, -} from "react"; - -import { beginReadonly, endReadonly } from "./react.js"; -import { useLastRenderRef } from "./updating-ref.js"; -import { UNINITIALIZED } from "./utils.js"; - -type State = "mounting" | "mounted" | "remounting" | "unmounted"; - -type UseLifecycleBuilder = ( - builder: ResourceBuilder, - args: A, - prev?: T | undefined -) => T; -type Validator = (args: V, prev: V) => boolean; - -interface Options { - readonly props?: A | undefined; - readonly validate?: V; - readonly with?: Validator; -} - -export function useLifecycle( - options: Options = {} -): { - render: (build: UseLifecycleBuilder) => T; -} { - const { props } = options; - let validateWith: Validator | undefined; - let validate: V | undefined; - - if ("validate" in options) { - validate = options.validate; - validateWith = options.with ?? Object.is; - } - - return { - render: ((build: UseLifecycleBuilder) => { - const [, setNotify] = useState({}); - const notify = () => { - setNotify({}); - }; - const state = useRef("mounting"); - - const initialRef = useRef< - UNINITIALIZED | ResourceInstance - >(UNINITIALIZED); - - if (initialRef.current === UNINITIALIZED) { - initialRef.current = ResourceBuilder.build({ - build, - notify, - validateWith, - args: props, - }); - } else { - if (state.current === "mounted") { - // If we're already mounted, that means we're updating, so call the update callback. - initialRef.current.run("update", props); - } else { - // If we're remounting, we're effectively in the initial state, and the work already happened - // in `useLayoutEffect`, so don't do anything here. - state.current = "mounted"; - } - } - - const ref = initialRef as MutableRefObject< - ResourceInstance - >; - - // The callback to useLayoutEffect is created once, but should see the most recent rendered args. - const { ref: renderedArgs } = useLastRenderRef(props); - - const { ref: currentValidate, prev: prevValidate } = - useLastRenderRef(validate); - - if (prevValidate !== UNINITIALIZED) { - const isValid = ref.current.validate( - currentValidate.current as never, - prevValidate as never - ); - - if (!isValid) { - ref.current.run("cleanup", renderedArgs.current); - - ref.current = ref.current.remount(renderedArgs.current); - ref.current.run("layout", renderedArgs.current); - } - } - - useLayoutEffect(() => { - switch (state.current) { - case "unmounted": { - notify(); - ref.current = ref.current.remount(renderedArgs.current); - - state.current = "remounting"; - break; - } - default: { - state.current = "mounted"; - } - } - - ref.current.run("layout", renderedArgs.current); - - return () => { - ref.current.run("cleanup", renderedArgs.current); - state.current = "unmounted"; - }; - }, []); - - useEffect(() => { - ref.current.run("idle", renderedArgs.current); - - // we don't need to return a cleanup function since we already did that in useLayoutEffect - }, []); - - return ref.current.instance; - }) as (build: unknown) => T, - }; -} - -class ResourceInstance { - #builder: ResourceBuilder; - #instance: T; - - constructor(builder: ResourceBuilder, instance: T) { - this.#builder = builder; - this.#instance = instance; - } - - get instance(): T { - return this.#instance; - } - - validate(current: V, prev: V): boolean { - return ResourceBuilder.validate(this.#builder, current, prev); - } - - remount(args: A): ResourceInstance { - return ResourceBuilder.remount(this.#builder, args, this.#instance); - } - - run(event: "cleanup" | "layout" | "idle" | "update", args: A): void { - ResourceBuilder.run(this.#builder, event, args); - } -} - -export interface RegisterLifecycleHandlers
    { - cleanup: (cleanup: (args: A) => void) => void; - update: (update: (args: A) => void) => void; - layout: (onLayout: (args: A) => void) => void; - idle: (onIdle: (args: A) => void) => void; -} - -class ResourceBuilder { - static build({ - build, - notify, - args, - validateWith, - prev, - }: { - build: UseLifecycleBuilder; - notify: () => void; - args: A; - validateWith: Validator | undefined; - prev?: T | undefined; - }): ResourceInstance { - const builder = new ResourceBuilder( - build as UseLifecycleBuilder, - validateWith, - notify - ); - beginReadonly(); - try { - const instance = new ResourceInstance( - builder, - build(builder, args, prev) - ); - endReadonly(); - return instance; - } catch (e) { - endReadonly(); - throw e; - } - } - - static remount( - builder: ResourceBuilder, - args: A, - prev: T - ): ResourceInstance { - return ResourceBuilder.build({ - build: builder.#build as UseLifecycleBuilder, - validateWith: builder.#validateWith, - notify: builder.notify, - args, - prev, - }); - } - - static run( - resource: ResourceBuilder, - event: "cleanup" | "layout" | "idle" | "update", - args: A - ): void { - for (const callback of resource.#on[event]) { - callback(args); - } - } - - static validate( - resource: ResourceBuilder, - current: V, - prev: V - ): boolean { - if (resource.#validateWith === undefined) { - return true; - } - - return resource.#validateWith(current, prev); - } - - readonly #build: UseLifecycleBuilder; - readonly #validateWith: Validator | undefined; - - #on = { - cleanup: new Set<(args: A) => void>(), - layout: new Set<(args: A) => void>(), - idle: new Set<(args: A) => void>(), - update: new Set<(args: A) => void>(), - }; - - readonly notify: () => void; - - readonly on: RegisterLifecycleHandlers = { - cleanup: (cleanup: (args: A) => void): void => { - this.#on.cleanup.add(cleanup); - }, - - update: (update: (args: A) => void): void => { - this.#on.update.add(update); - }, - - layout: (onLayout: (args: A) => void): void => { - this.#on.layout.add(onLayout); - }, - - idle: (onIdle: (args: A) => void): void => { - this.#on.idle.add(onIdle); - }, - }; - - constructor( - build: UseLifecycleBuilder, - validator: Validator | undefined, - notify: () => void - ) { - this.#build = build; - this.#validateWith = validator; - this.notify = notify; - } -} diff --git a/packages/react/use-strict-lifecycle/src/updating-ref.ts b/packages/react/use-strict-lifecycle/src/updating-ref.ts index 0f273a85..bdaeb0d8 100644 --- a/packages/react/use-strict-lifecycle/src/updating-ref.ts +++ b/packages/react/use-strict-lifecycle/src/updating-ref.ts @@ -11,83 +11,26 @@ export interface Ref { } /** - * This interface allows you to change the ref returned by - * {@link useMutableUpdatingRef} to a more expansive value than the ones returned by - * `initial()` or `update()`, while still allowing code that runs *inside* the - * render function to assume the narrower meaning. + * This function takes a callback that is used to initialize a ref, and returns + * a tuple of `[ref, isUpdate]`. * - * Even if you update the {@link ref} with a more expansive type, the next time - * the containing component renders, its `update()` function will run again, - * converting the wider definition back into the narrower meaning. - * - * For example, this allows you to set the ref to something else in - * {@link useEffect}, and then use that information in `update()` to convert - * what {@link useEffect} did back into the original value. - * - * This is sometimes necessary to coordinate between: - * - * - top-level rendering code, which is allowed to use hooks - * - JSX returned by top-level rendering code, which wants immediate access to - * values - * - useEffect and useLayoutEffect, which have access to component elements - * (installed via `ref`), but which cannot use hooks or produce JSX in the - * context of the top-level render. + * The first time `useInitializedRef` is called, it will call the callback and + * store the result in the ref, and return `[ref, false]`. On subsequent calls, + * it will return `[ref, true]` (the same ref). */ -export interface MutableUpdatingRef { - /** - * The value returned by `initial()` or `update()` in {@link useMutableUpdatingRef}. - * - */ - readonly value: T; - /** - * A React Ref that you can update with a more expansive type. - */ - readonly ref: MutableRefObject; -} - -export function useUpdatingVariable(options: { - initial: () => T; - update: (value: T) => T | void; -}): T { - return useUpdatingRef(options).ref.current; -} - -/** - * `useUpdatingRef` is a React hook that lets you create a value on initial render and keep it up - * to date on subsequent renders. - * - * ## Details - * - * On the first render, this hook calls the `initial` function and populates a Ref with the - * value the `initial` function returned. - * - * On subsequent renders, this hook calls the `update` function with the previous value. If the - * `update` function returns a value, it becomes the new value of the Ref. - * - * Either way, this function returns a `Ref` containing the current value. - */ -export function useUpdatingRef({ - initial, - update, -}: { - initial: () => T; - update: (value: T) => T | void; -}): { ref: Ref; prev: T | UNINITIALIZED } { - const ref = useRef(UNINITIALIZED); - const prev = ref.current; +export function useInitializedRef( + initial: () => T +): [ref: MutableRefObject, isUpdate: boolean] { + const ref = useRef(UNINITIALIZED as T | UNINITIALIZED); if (ref.current === UNINITIALIZED) { ref.current = initial(); + return [ref as MutableRefObject, false]; } else { - const next = update(ref.current); - - if (next !== undefined) { - ref.current = next; - } + return [ref as MutableRefObject, true]; } - - return { ref, prev } as { ref: Ref; prev: T | UNINITIALIZED }; } + /** * This function takes a piece of state that is available as a per-render value * (e.g. props or the first element of the array returned by useState) and @@ -101,12 +44,12 @@ export function useUpdatingRef({ * useLayoutEffect callbacks without needing to worry about the possibility of * stale closures. */ -export function useLastRenderRef(state: S): { - ref: Ref; - prev: S | UNINITIALIZED; -} { - return useUpdatingRef({ - initial: () => state, - update: () => state, - }); +export function useLastRenderRef( + state: S +): [ref: Ref, prev: S | UNINITIALIZED] { + const ref = useRef(UNINITIALIZED); + const prev = ref.current; + + ref.current = state; + return [ref as Ref, prev]; } diff --git a/packages/react/use-strict-lifecycle/src/utils.ts b/packages/react/use-strict-lifecycle/src/utils.ts index 90f0f35c..2a2dd453 100644 --- a/packages/react/use-strict-lifecycle/src/utils.ts +++ b/packages/react/use-strict-lifecycle/src/utils.ts @@ -1,52 +1,36 @@ -import { checker } from "./checker.js"; - export interface Check { test: (value: In) => value is Out; failure: (value: In) => string; } +export type CheckFn = ( + value: In +) => Check; + export type AdHocCheck = [ predicate: (value: In) => value is Out, message: (value: In) => string ]; -export function check( - value: In, - test: (value: In) => value is Out, - message: (value: In) => string -): asserts value is Out; -export function check( - value: In, - assertion: Check -): asserts value is Out; -export function check( - value: In, - ...validator: [Check] | AdHocCheck -): asserts value is Out { - checkValue(value, checker(validator)); +type OutValue, In> = C extends { + test: (value: In) => value is infer Out extends In; } + ? Out + : never; -export function checked( - value: In, - test: (value: In) => value is Out, - message: (value: In) => string -): Out; -export function checked( +export function checked>( value: In, - assertion: Check -): Out; -export function checked( - value: In, - ...validator: [Check] | AdHocCheck -): Out { - checkValue(value, checker(validator)); + assertion: C +): OutValue { + check(value, assertion); return value; } -function checkValue( +export function check>( value: In, - { test, failure }: Check -): asserts value is Out { + assertion: C +): asserts value is OutValue { + const { test, failure } = assertion(value); if (!test(value)) { const error = typeof failure === "string" ? failure : failure(value); throw Error(error); @@ -63,6 +47,38 @@ export function exhaustive(_value: never, variable: string): never { throw Error(`Exhaustive check failed for ${variable}`); } +export function isInitialized( + _: T | UNINITIALIZED +): Check { + return { + test: (value): value is T => value !== UNINITIALIZED, + failure: (value) => + `Expected value to be initialized, but got ${String(value)}`, + }; +} + +export function isDefined( + _: T | undefined | null +): Check { + return { + test: (value): value is T => value !== undefined && value !== null, + failure: (value) => + `Expected value to be defined, but got ${String(value)}`, + }; +} + +export function mapEntries, T>( + record: R, + callback: (value: R[keyof R], key: keyof R) => T +): { [K in keyof R]: T } { + return Object.fromEntries( + Object.entries(record).map(([key, value]) => [ + key, + callback(value as R[keyof R], key), + ]) + ) as { [K in keyof R]: T }; +} + // Avoid needing an additional import export const UNINITIALIZED = Symbol.for("starbeam.UNINITIALIZED"); export type UNINITIALIZED = typeof UNINITIALIZED; diff --git a/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts b/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts index 897bd701..9f834f2d 100644 --- a/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts @@ -1,9 +1,7 @@ // @vitest-environment jsdom -import { type Ref, useUpdatingRef } from "@starbeam/use-strict-lifecycle"; import { html, react, testReact } from "@starbeam-workspace/react-test-utils"; import { useEffect, useLayoutEffect, useRef, useState } from "react"; -import { expect } from "vitest"; testReact( "testReact (testing the test infra)", @@ -45,38 +43,3 @@ testReact( }); } ); - -testReact>( - "useUpdatingRef", - async (root, mode) => { - const result = await root - .expectStable((value) => value) - .expectHTML((ref) => `${ref.current.count}`) - .render((test) => { - const { ref } = useUpdatingRef({ - initial: () => ({ count: 0 }), - update: (counter) => { - counter.count++; - return counter; - }, - }); - - test.value(ref); - - return react.fragment(ref.current.count); - }, undefined); - - const ref = result.value; - - expect(ref.current.count).toBe(0); - - await result.rerender(); - - expect(ref.current.count).toBe( - mode.match({ - loose: () => 1, - strict: () => 2, - }) - ); - } -); From 30215b267841a712cf872d5f07f4ec25bfe97e89 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 10 Apr 2023 00:36:46 -0700 Subject: [PATCH 34/46] React cleanup --- packages/react/react/src/context-provider.ts | 5 ++ packages/react/react/src/starbeam/instance.ts | 88 +++++++++---------- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/packages/react/react/src/context-provider.ts b/packages/react/react/src/context-provider.ts index 1cef576d..f18966e8 100644 --- a/packages/react/react/src/context-provider.ts +++ b/packages/react/react/src/context-provider.ts @@ -66,6 +66,11 @@ export function useStarbeamApp({ return app; } +export function verifiedApp(app: ReactApp | null, feature: string): ReactApp { + if (!app) missingApp(feature); + return app; +} + export function missingApp(feature: string): never { throw Error( `You are attempting to use a feature of Starbeam (${feature}) that depends on the current app, but you didn't wrap your application in the \`Starbeam\` component.` diff --git a/packages/react/react/src/starbeam/instance.ts b/packages/react/react/src/starbeam/instance.ts index 6eb02b95..47dd57c2 100644 --- a/packages/react/react/src/starbeam/instance.ts +++ b/packages/react/react/src/starbeam/instance.ts @@ -7,7 +7,7 @@ import { service as starbeamService } from "@starbeam/service"; import type { RegisterLifecycleHandlers } from "@starbeam/use-strict-lifecycle"; import { isPresent, verified } from "@starbeam/verify"; -import { missingApp, type ReactApp } from "../context-provider.js"; +import { type ReactApp, verifiedApp } from "../context-provider.js"; import { type Callback, Handlers, @@ -24,9 +24,13 @@ export interface StarbeamInstance { export interface InternalStarbeamInstance extends StarbeamInstance { readonly deactivate: () => void; - readonly reactivate: (lifecycle: Handlers) => InternalStarbeamInstance; + readonly reactivate: (lifecycle: Handlers) => void; } +/** + * Activates this Starbeam instance: creates a new one if it doesn't exist, or + * reactivates an existing one if the component is being remounted. + */ export function activate({ starbeam, on, @@ -35,20 +39,23 @@ export function activate({ }: { starbeam: InternalStarbeamInstance | undefined; on: RegisterLifecycleHandlers; - app: ReactApp | null; notify: Callback; }): InternalStarbeamInstance { const handlers = Handlers(); - const instance = starbeam - ? starbeam.reactivate(handlers) - : StarbeamInstance(handlers, app, notify); + if (starbeam) starbeam.reactivate(handlers); + const instance = starbeam ?? StarbeamInstance(handlers, app, notify); setup({ on, handlers, instance }); return instance; } +/** + * Sets up the lifecycle handlers for this Starbeam instance. If the component is + * being remounted, the previous handlers were already cleaned up, so we need to + * set up new ones. + */ function setup({ on, handlers, @@ -76,12 +83,29 @@ export function StarbeamInstance( ): InternalStarbeamInstance { let handlers: Handlers | null = lifecycle; - function service(resource: IntoResourceBlueprint): Resource { - if (!app) missingApp("useStarbeam"); - return starbeamService(resource, { app }); - } + function use( + resource: IntoResourceBlueprint, + options?: O + ): Reactive> { + const resourceCell = Cell(undefined as Resource | undefined); + + verified(handlers, isPresent).layout.add(() => { + resourceCell.set( + starbeamUse(resource, { lifetime: verified(handlers, isPresent) }) + ); + notify(); + }); + + const formula = CachedFormula( + () => resourceCell.current?.current ?? options?.initial + ); - const use = useFn(() => verified(handlers, isPresent), notify); + verified(handlers, isPresent).cleanup.add(() => { + PUBLIC_TIMELINE.on.change(formula, notify); + }); + + return formula as Reactive; + } function deactivate() { if (handlers) { @@ -91,20 +115,14 @@ export function StarbeamInstance( handlers = null; } - function reactivate(lifecycle: Handlers): InternalStarbeamInstance { - handlers = lifecycle; - return instance; - } - - const instance = { + return { on: onHandlers(() => verified(handlers, isPresent)), use, - service, + service: (resource: IntoResourceBlueprint): Resource => + starbeamService(resource, { app: verifiedApp(app, "service") }), deactivate, - reactivate, - } satisfies InternalStarbeamInstance; - - return instance; + reactivate: (newHandlers) => (handlers = newHandlers), + }; } type PropagateUndefined = O extends undefined ? undefined : never; @@ -113,29 +131,3 @@ type UseFn = ( resource: IntoResourceBlueprint, options?: O ) => Reactive>; - -function useFn(handlers: () => Handlers, notify: Callback): UseFn { - function use( - resource: IntoResourceBlueprint, - options?: O - ): Reactive> { - const resourceCell = Cell(undefined as Resource | undefined); - - handlers().layout.add(() => { - resourceCell.set(starbeamUse(resource, { lifetime: handlers })); - notify(); - }); - - const formula = CachedFormula( - () => resourceCell.current?.current ?? options?.initial - ); - - handlers().cleanup.add(() => { - PUBLIC_TIMELINE.on.change(formula, notify); - }); - - return formula as Reactive; - } - - return use; -} From 68ae89a52826c653cb854fe236115bdc08a0133c Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 10 Apr 2023 01:03:53 -0700 Subject: [PATCH 35/46] Fix resource exports --- package.json | 2 +- packages/universal/resource/index.ts | 1 + packages/universal/resource/src/api.ts | 17 +++++++++-------- packages/universal/resource/src/resource.ts | 2 +- pnpm-lock.yaml | 3 +++ workspace/test-utils/package.json | 1 + workspace/test-utils/src/test-resource.ts | 3 ++- 7 files changed, 18 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 09c37042..6a441087 100644 --- a/package.json +++ b/package.json @@ -178,6 +178,6 @@ }, "volta": { "node": "19.8.1", - "pnpm": "8.1.1" + "pnpm": "8.2.0" } } diff --git a/packages/universal/resource/index.ts b/packages/universal/resource/index.ts index b4395dcf..7fef27d0 100644 --- a/packages/universal/resource/index.ts +++ b/packages/universal/resource/index.ts @@ -1,3 +1,4 @@ +export type { ResourceBlueprint, ResourceBrand } from "./src/api.js"; export * from "./src/api.js"; export { lifetime, type ResourceRun } from "./src/resource.js"; export { ResourceList } from "./src/resource-list.js"; diff --git a/packages/universal/resource/src/api.ts b/packages/universal/resource/src/api.ts index 44d3d55b..fc202c7f 100644 --- a/packages/universal/resource/src/api.ts +++ b/packages/universal/resource/src/api.ts @@ -1,5 +1,5 @@ import type { Description } from "@starbeam/interfaces"; -import type { FormulaFn, ReadValue } from "@starbeam/reactive"; +import type { FormulaFn } from "@starbeam/reactive"; import { ResourceBlueprintImpl, type UseOptions } from "./resource.js"; import type { ResourceConstructor } from "./types.js"; @@ -27,17 +27,18 @@ export function use( return ResourceBlueprintImpl.evaluate(blueprint, options, options.lifetime); } -declare const ResourceBrand: unique symbol; -export type Resource = FormulaFn> & { +export declare const ResourceBrand: unique symbol; +export type Resource = FormulaFn & { [ResourceBrand]: true; }; export const Resource = ResourceBlueprintImpl.create; export { isResource } from "./resource.js"; -export type ResourceBlueprint = - | ResourceBlueprintImpl - | ResourceBlueprintImpl; +export type ResourceBlueprint = ResourceBlueprintImpl< + T, + M +>; export type IntoResourceBlueprint = | ResourceBlueprint @@ -49,12 +50,12 @@ export function IntoResourceBlueprint( if (isResourceBlueprint(value)) { return value; } else { - return Resource(value); + return Resource(value) as ResourceBlueprint; } } export function isResourceBlueprint( value: unknown -): value is ResourceBlueprint { +): value is ResourceBlueprint { return value instanceof ResourceBlueprintImpl; } diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index 20516ada..3650442c 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -115,7 +115,7 @@ export class ResourceBlueprintImpl { ): ResourceBlueprint { return isResourceBlueprint(value) ? value - : ResourceBlueprintImpl.create(value); + : (ResourceBlueprintImpl.create(value) as ResourceBlueprint); } static run( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9341500e..e082c301 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1917,6 +1917,9 @@ importers: workspace/test-utils: dependencies: + '@starbeam/resource': + specifier: workspace:^ + version: link:../../packages/universal/resource '@starbeam/runtime': specifier: workspace:^ version: link:../../packages/universal/runtime diff --git a/workspace/test-utils/package.json b/workspace/test-utils/package.json index 9ec3d4de..329cfe78 100644 --- a/workspace/test-utils/package.json +++ b/workspace/test-utils/package.json @@ -24,6 +24,7 @@ "test:types": "tsc -b" }, "dependencies": { + "@starbeam/resource": "workspace:^", "@starbeam/runtime": "workspace:^", "@starbeam/universal": "workspace:^", "@starbeam/verify": "workspace:^" diff --git a/workspace/test-utils/src/test-resource.ts b/workspace/test-utils/src/test-resource.ts index 1b321378..9a4780e2 100644 --- a/workspace/test-utils/src/test-resource.ts +++ b/workspace/test-utils/src/test-resource.ts @@ -1,4 +1,5 @@ -import { LIFETIME, Resource } from "@starbeam/universal"; +import { Resource } from "@starbeam/resource"; +import { LIFETIME } from "@starbeam/runtime"; import { isPresent, verified } from "@starbeam/verify"; export const TestResource = Resource((r) => { From c0ea070ced35b2327ad94a59a662914575603023 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 12:55:54 -0700 Subject: [PATCH 36/46] Fixes jsnation smoke test --- demos/react-jsnation/package.json | 1 + demos/react-jsnation/src/components/DataTable.tsx | 2 +- demos/react-jsnation/tests/package.json | 1 + pnpm-lock.yaml | 12 +++++++----- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/demos/react-jsnation/package.json b/demos/react-jsnation/package.json index 77869374..80865edf 100644 --- a/demos/react-jsnation/package.json +++ b/demos/react-jsnation/package.json @@ -40,6 +40,7 @@ "@starbeam/collections": "workspace:^", "@starbeam/debug": "workspace:^", "@starbeam/react": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/universal": "workspace:^", "purecss": "3.0.0", "react": "^18.2.0", diff --git a/demos/react-jsnation/src/components/DataTable.tsx b/demos/react-jsnation/src/components/DataTable.tsx index 9f01206c..7e4d25c5 100644 --- a/demos/react-jsnation/src/components/DataTable.tsx +++ b/demos/react-jsnation/src/components/DataTable.tsx @@ -1,6 +1,6 @@ import { useProp, useReactive, useSetup } from "@starbeam/react"; -import { Cell, Formula } from "@starbeam/universal"; import type { FormEvent } from "react"; +import { Cell, CachedFormula as Formula } from "@starbeam/reactive"; import { People, type Person } from "../lib/people.js"; import { type Row, Table } from "../lib/table.js"; diff --git a/demos/react-jsnation/tests/package.json b/demos/react-jsnation/tests/package.json index 24cbfabc..842e5bc7 100644 --- a/demos/react-jsnation/tests/package.json +++ b/demos/react-jsnation/tests/package.json @@ -22,6 +22,7 @@ }, "devDependencies": { "@testing-library/react": "^13.4.0", + "jsdom": "^21.1.1", "@types/react": "^18.0.26" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e082c301..7fc172f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -290,6 +290,9 @@ importers: '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../packages/universal/reactive '@starbeam/universal': specifier: workspace:^ version: link:../../packages/universal/universal @@ -346,6 +349,9 @@ importers: '@types/react': specifier: ^18.0.26 version: 18.0.26 + jsdom: + specifier: ^21.1.1 + version: 21.1.1 demos/react-lite-query: dependencies: @@ -8653,10 +8659,6 @@ packages: /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - /punycode@2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -9497,7 +9499,7 @@ packages: engines: {node: '>=6'} dependencies: psl: 1.9.0 - punycode: 2.1.1 + punycode: 2.3.0 universalify: 0.2.0 url-parse: 1.5.10 From 6325c4e08e70b739f6649137cafca00ea3f08e59 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 13:04:49 -0700 Subject: [PATCH 37/46] Avoid "no test suite" CI fail --- packages/universal/reactive/tests/cell.spec.ts | 9 +++++++++ packages/universal/reactive/tests/package.json | 3 ++- pnpm-lock.yaml | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 packages/universal/reactive/tests/cell.spec.ts diff --git a/packages/universal/reactive/tests/cell.spec.ts b/packages/universal/reactive/tests/cell.spec.ts new file mode 100644 index 00000000..0128b628 --- /dev/null +++ b/packages/universal/reactive/tests/cell.spec.ts @@ -0,0 +1,9 @@ +import { Cell } from "@starbeam/reactive"; +import { describe, test, expect } from "@starbeam-workspace/test-utils"; + +describe("Cell", () => { + test("its current property works like a normal property", () => { + const cell = Cell(1); + expect(cell.current).toBe(1); + }); +}); diff --git a/packages/universal/reactive/tests/package.json b/packages/universal/reactive/tests/package.json index 09086df5..26e977a0 100644 --- a/packages/universal/reactive/tests/package.json +++ b/packages/universal/reactive/tests/package.json @@ -12,6 +12,7 @@ "@starbeam/interfaces": "workspace:^", "@starbeam/reactive": "workspace:^", "@starbeam/runtime": "workspace:^", - "@starbeam/shared": "workspace:^" + "@starbeam/shared": "workspace:^", + "@starbeam-workspace/test-utils": "workspace:^" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7fc172f4..94cc5461 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1109,6 +1109,9 @@ importers: packages/universal/reactive/tests: dependencies: + '@starbeam-workspace/test-utils': + specifier: workspace:^ + version: link:../../../../workspace/test-utils '@starbeam/debug': specifier: workspace:^ version: link:../../debug From 127b2a0f436855eb187a0beae82478757a0fdf1d Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 13:55:59 -0700 Subject: [PATCH 38/46] Fix typecheck Some of these changes just formalize minor regressions in this branch, especially in debugging infra. --- @types/ansicolor/index.d.ts | 6 +- @types/ansicolor/package.json | 1 + .../preact-hello-world/src/components/App.tsx | 14 +-- .../src/components/Card.tsx | 5 +- demos/preact/package.json | 3 + .../components/formatter/DateFormatter-v1.tsx | 2 +- .../components/formatter/DateFormatter-v3.tsx | 9 +- .../formatter/DateFormatterFinal.tsx | 5 +- demos/react-jsnation/package.json | 2 + .../src/components/DateFormatter.tsx | 11 +- demos/react-lite-query/src/App.tsx | 9 +- demos/react-lite-query/src/lib/fetch.ts | 74 +++++++----- demos/react-lite-query/src/lib/use-query.ts | 8 +- demos/react-query/src/lib/query.ts | 2 +- .../src/components/StockDetails.tsx | 6 +- .../react-store/src/components/DataTable.tsx | 6 +- .../src/components/DateFormatter.tsx | 9 +- .../components/formatter/DateFormatter-v2.tsx | 2 +- .../components/formatter/DateFormatter-v3.tsx | 2 +- .../formatter/DateFormatterFinal.tsx | 19 +-- packages/preact/preact/src/resource.ts | 8 +- packages/react/react/src/debug/warnings.ts | 113 +++++++++--------- packages/react/react/src/use-service.ts | 4 +- packages/universal/core-utils/src/array.ts | 10 +- packages/universal/debug/src/setup.ts | 2 +- packages/universal/universal/index.ts | 25 ++-- packages/x/devtool/index.tsx | 3 +- packages/x/devtool/src/log/cell.tsx | 17 ++- packages/x/devtool/src/log/describe.tsx | 16 ++- packages/x/devtool/src/log/frame.tsx | 17 +-- packages/x/devtool/src/log/log.tsx | 20 ++-- packages/x/devtool/src/log/shared.ts | 14 +-- packages/x/devtool/src/log/tabs.tsx | 4 +- packages/x/devtool/src/log/ui.tsx | 6 +- ...-reactive.tsx => single-reactive.tsx.todo} | 19 ++- pnpm-lock.yaml | 18 +++ workspace/package/src/query/filters.ts | 2 +- workspace/reporter/package.json | 2 + workspace/reporter/src/table.ts | 16 +-- workspace/shared/index.ts | 1 + 40 files changed, 292 insertions(+), 220 deletions(-) rename packages/x/devtool/src/single/{single-reactive.tsx => single-reactive.tsx.todo} (89%) diff --git a/@types/ansicolor/index.d.ts b/@types/ansicolor/index.d.ts index a6eb6d8d..ec01a6c2 100644 --- a/@types/ansicolor/index.d.ts +++ b/@types/ansicolor/index.d.ts @@ -38,7 +38,11 @@ type FgColor = Expand<{ default: Color; }>; -export type Color = BgColor & FgColor & ((text: string) => string); +interface Methods { + strip: Color; +} + +export type Color = Methods & BgColor & FgColor & ((text: string) => string); const DEFAULT: Color; export default DEFAULT; diff --git a/@types/ansicolor/package.json b/@types/ansicolor/package.json index 2a0617e6..20259fc5 100644 --- a/@types/ansicolor/package.json +++ b/@types/ansicolor/package.json @@ -1,6 +1,7 @@ { "private": true, "name": "@types/ansicolor", + "type":"module", "version": "1.0.0", "types": "index.d.ts", "exports": { diff --git a/demos/preact-hello-world/src/components/App.tsx b/demos/preact-hello-world/src/components/App.tsx index ec727581..e23c7cc4 100644 --- a/demos/preact-hello-world/src/components/App.tsx +++ b/demos/preact-hello-world/src/components/App.tsx @@ -1,13 +1,13 @@ -import { create, createCell, use } from "@starbeam/preact"; -import type { Factory, ResourceBlueprint } from "@starbeam/universal"; -import { Cell, Resource, service } from "@starbeam/universal"; +import { create, createCell, service, use } from "@starbeam/preact"; +import type { ResourceBlueprint } from "@starbeam/universal"; +import { Cell, Resource } from "@starbeam/universal"; import type { JSX } from "preact"; import { useState } from "preact/hooks"; import Card from "./Card.jsx"; export default function App(): JSX.Element { - const counter = create(Count); + const counter = use(Count); const [showChild, setShowChild] = useState(true); const cell = createCell(0, "cell"); @@ -112,7 +112,7 @@ function UsingCounterService({ Service, }: { name: string; - Service: Factory; + Service: ResourceBlueprint; }): JSX.Element { const counter = service(Service); @@ -157,7 +157,7 @@ interface CounterData { increment: () => void; } -function Count(): CounterData { +const Count = Resource(() => { const count = Cell(0, "data count"); return { @@ -168,7 +168,7 @@ function Count(): CounterData { count.current++; }, }; -} +}); function CounterWithCleanup( status: Cell = Cell("new") diff --git a/demos/preact-hello-world/src/components/Card.tsx b/demos/preact-hello-world/src/components/Card.tsx index 0f69a6ff..caadb8d8 100644 --- a/demos/preact-hello-world/src/components/Card.tsx +++ b/demos/preact-hello-world/src/components/Card.tsx @@ -1,7 +1,6 @@ import "preact"; -import type { ComponentChildren } from "preact"; -import type { JSXInternal } from "preact/src/jsx.js"; +import type { ComponentChildren, JSX } from "preact"; export default function Card({ children, @@ -9,7 +8,7 @@ export default function Card({ }: { children?: ComponentChildren; class?: string; -}): JSXInternal.Element { +}): JSX.Element { const classes = ["card"]; if (className) classes.push(className); return
    {children}
    ; diff --git a/demos/preact/package.json b/demos/preact/package.json index 905f544a..006cbe22 100644 --- a/demos/preact/package.json +++ b/demos/preact/package.json @@ -37,8 +37,11 @@ }, "dependencies": { "@starbeam/collections": "workspace:^", + "@starbeam/interfaces": "workspace:^", "@starbeam/preact": "workspace:^", + "@starbeam/reactive": "workspace:^", "@starbeam/universal": "workspace:^", + "@starbeam/resource":"workspace:^", "preact": "^10.11.3", "purecss": "^3.0.0" }, diff --git a/demos/preact/src/components/formatter/DateFormatter-v1.tsx b/demos/preact/src/components/formatter/DateFormatter-v1.tsx index 5b755d32..6a93f8bf 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v1.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v1.tsx @@ -1,6 +1,6 @@ import js from "@starbeam/collections"; import { create } from "@starbeam/preact"; -import { Formula } from "@starbeam/universal"; +import { Formula } from "@starbeam/reactive"; import type { JSX } from "preact"; import { formatLocale, SYSTEM_LOCALE, SYSTEM_TZ } from "../intl.js"; diff --git a/demos/preact/src/components/formatter/DateFormatter-v3.tsx b/demos/preact/src/components/formatter/DateFormatter-v3.tsx index 1cb68e97..65f6f91b 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v3.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v3.tsx @@ -1,7 +1,12 @@ import js from "@starbeam/collections"; import { create, use } from "@starbeam/preact"; -import type { Reactive, ResourceBlueprint } from "@starbeam/universal"; -import { Cell, Resource, Static } from "@starbeam/universal"; +import type { Reactive } from "@starbeam/interfaces"; +import { + Cell, + Resource, + Static, + type ResourceBlueprint, +} from "@starbeam/universal"; import type { JSX } from "preact"; import { diff --git a/demos/preact/src/components/formatter/DateFormatterFinal.tsx b/demos/preact/src/components/formatter/DateFormatterFinal.tsx index 0422a261..9eebb880 100644 --- a/demos/preact/src/components/formatter/DateFormatterFinal.tsx +++ b/demos/preact/src/components/formatter/DateFormatterFinal.tsx @@ -1,7 +1,5 @@ import js from "@starbeam/collections"; import { create, use } from "@starbeam/preact"; -import type { ResourceBlueprint } from "@starbeam/universal"; -import { type Reactive, Cell, Resource } from "@starbeam/universal"; import type { JSX } from "preact/jsx-runtime"; import { @@ -11,6 +9,9 @@ import { TIME_ZONES, timeZoneName, } from "../intl.js"; +import { Cell } from "@starbeam/reactive"; +import type { Reactive } from "@starbeam/interfaces"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; export default function DateFormatterStarbeam(props: { locale: string; diff --git a/demos/react-jsnation/package.json b/demos/react-jsnation/package.json index 80865edf..31f470a1 100644 --- a/demos/react-jsnation/package.json +++ b/demos/react-jsnation/package.json @@ -39,8 +39,10 @@ "dependencies": { "@starbeam/collections": "workspace:^", "@starbeam/debug": "workspace:^", + "@starbeam/interfaces": "workspace:^", "@starbeam/react": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/universal": "workspace:^", "purecss": "3.0.0", "react": "^18.2.0", diff --git a/demos/react-jsnation/src/components/DateFormatter.tsx b/demos/react-jsnation/src/components/DateFormatter.tsx index a4d21703..375d2155 100644 --- a/demos/react-jsnation/src/components/DateFormatter.tsx +++ b/demos/react-jsnation/src/components/DateFormatter.tsx @@ -1,10 +1,4 @@ import { useProp, useSetup } from "@starbeam/react"; -import { - type Reactive, - type ResourceBlueprint, - Cell, - Resource, -} from "@starbeam/universal"; import { formatLocale, @@ -13,6 +7,9 @@ import { TIME_ZONES, timeZoneName, } from "./intl.js"; +import type { Reactive } from "@starbeam/interfaces"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; +import { Cell } from "@starbeam/reactive"; export default function (props: { locale: string }): JSX.Element { const locale = useProp(props.locale); @@ -50,7 +47,7 @@ export default function (props: { locale: string }): JSX.Element { -

    {date.current.formatted}

    +

    {date.current?.formatted}

    ); }; diff --git a/demos/react-lite-query/src/App.tsx b/demos/react-lite-query/src/App.tsx index 50b4ac14..1fcec8b2 100644 --- a/demos/react-lite-query/src/App.tsx +++ b/demos/react-lite-query/src/App.tsx @@ -1,15 +1,14 @@ import "./App.css"; -import { - type DevtoolsOptions, - type UpdatePane, - TabsPane, -} from "@starbeamx/devtool"; +import { type UpdatePane, TabsPane } from "@starbeamx/devtool"; import { Axios } from "axios"; import { useEffect, useRef } from "react"; import useQuery from "./lib/use-query.js"; +type FIXME = any; +type DevtoolsOptions = FIXME; + export default function App(): JSX.Element { const ref = useRef(null); const devtools = useRef>(); diff --git a/demos/react-lite-query/src/lib/fetch.ts b/demos/react-lite-query/src/lib/fetch.ts index 80110936..528548a7 100644 --- a/demos/react-lite-query/src/lib/fetch.ts +++ b/demos/react-lite-query/src/lib/fetch.ts @@ -1,5 +1,6 @@ -import { type Description, type Stack, callerStack } from "@starbeam/debug"; import { reactive } from "@starbeam/collections"; +import type { CallStack, Description } from "@starbeam/interfaces"; +import { RUNTIME } from "@starbeam/runtime"; import { Cell } from "@starbeam/universal"; import { isPresent, verified } from "@starbeam/verify"; @@ -11,7 +12,7 @@ export class Queries { query( key: string, query: () => Promise, - description: Description + description?: Description | undefined ): Async { let result = this.#queries.get(key); @@ -53,13 +54,18 @@ interface Variant { readonly value: Cell; } -function selected(description: Description): Variant; -function selected(value: T, description: Description): Variant; +function selected( + description: Description | undefined +): Variant; +function selected( + value: T, + description: Description | undefined +): Variant; function selected( - ...args: [Description] | [unknown, Description] + ...args: [Description | undefined] | [unknown, Description | undefined] ): Variant { let value: unknown; - let description: Description; + let description: Description | undefined; if (args.length === 1) { value = undefined; @@ -71,29 +77,35 @@ function selected( return { selected: Cell(true, { - description: description.implementation("selected?", { - reason: "selected?", - }), + description: description?.implementation( + "cell", + "selected?", + "cell is selected" + ), }), value: Cell(value, { - description: description.implementation("value", { - reason: "value", - stack: callerStack(), - }), + description: description?.implementation( + "cell", + "value", + "cell value", + RUNTIME.callerStack?.() + ), }), }; } -function deselected(description: Description): Variant; -function deselected(description: Description): Variant { +function deselected(description: Description | undefined): Variant; +function deselected(description: Description | undefined): Variant { return { selected: Cell(false, { - description: description.implementation("selected?", { - reason: "selected?", - }), + description: description?.implementation( + "cell", + "selected?", + "cell is selected" + ), }), value: Cell(null as unknown, { - description: description.implementation("value", { reason: "value" }), + description: description?.implementation("cell", "value", "cell value"), }), }; } @@ -127,13 +139,21 @@ export type AsyncData = }; export class Async { - static idle(description: Description): Async { + static idle(description: Description | undefined): Async { return new Async( { - idle: Variant.selected(description.detail("variant", ["idle"])), - loading: Variant.deselected(description.detail("variant", ["loading"])), - loaded: Variant.deselected(description.detail("variant", ["loaded"])), - error: Variant.deselected(description.detail("variant", ["error"])), + idle: Variant.selected( + description?.detail("cell", "variant", ["idle"]) + ), + loading: Variant.deselected( + description?.detail("cell", "variant", ["loading"]) + ), + loaded: Variant.deselected( + description?.detail("cell", "variant", ["loaded"]) + ), + error: Variant.deselected( + description?.detail("cell", "variant", ["error"]) + ), }, "idle" ); @@ -147,7 +167,7 @@ export class Async { this.#currentType = current; } - asData(caller: Stack): AsyncData { + asData(caller = RUNTIME.callerStack?.()): AsyncData { switch (this.#currentType) { case "idle": return { state: "idle" }; @@ -187,13 +207,13 @@ export class Async { is>( type: K, - caller: Stack = callerStack() + caller = RUNTIME.callerStack?.() ): this is K extends "loaded" ? { data: T } : this { return this.#states[type].selected.read(caller); } get data(): T | null { - return this.#states.loaded.value.read(callerStack()); + return this.#states.loaded.value.read(RUNTIME.callerStack?.()); } idle(): this { diff --git a/demos/react-lite-query/src/lib/use-query.ts b/demos/react-lite-query/src/lib/use-query.ts index bc8df6af..a9c62785 100644 --- a/demos/react-lite-query/src/lib/use-query.ts +++ b/demos/react-lite-query/src/lib/use-query.ts @@ -1,4 +1,4 @@ -import type { Description } from "@starbeam/interfaces/index.js"; +import type { Description } from "@starbeam/interfaces"; import { useSetup } from "@starbeam/react"; import { RUNTIME } from "@starbeam/runtime"; @@ -11,7 +11,7 @@ export default function useQuery( description?: string | Description ): AsyncData { const desc = RUNTIME.debug - .desc("resource", description, "useQuery") + ?.desc("resource", description, "useQuery") ?.detail("formula", "query", [key]); return useSetup(({ on }) => { @@ -19,10 +19,10 @@ export default function useQuery( QUERIES.fetch(key).catch((e) => { console.error(e); }); - }, desc.implementation("on.idle", { reason: "on.idle" })); + }, desc?.implementation("resource", "on.idle", "on idle callback")); return () => { - return QUERIES.query(key, query, desc).asData(callerStack()); + return QUERIES.query(key, query, desc).asData(RUNTIME.callerStack?.()); }; }, desc).compute(); } diff --git a/demos/react-query/src/lib/query.ts b/demos/react-query/src/lib/query.ts index 7bfda573..cab2d187 100644 --- a/demos/react-query/src/lib/query.ts +++ b/demos/react-query/src/lib/query.ts @@ -1,5 +1,5 @@ import { reactive } from "@starbeam/collections"; -import { Cell, Freshness } from "@starbeam/universal"; +import { Cell, Freshness, Marker } from "@starbeam/universal"; import { CanceledError } from "axios"; import { type Serializable, serialize } from "./key.js"; diff --git a/demos/react-stock-ticker/src/components/StockDetails.tsx b/demos/react-stock-ticker/src/components/StockDetails.tsx index 346b62a6..26cffd6a 100644 --- a/demos/react-stock-ticker/src/components/StockDetails.tsx +++ b/demos/react-stock-ticker/src/components/StockDetails.tsx @@ -20,7 +20,7 @@ export function StockDetails({ const state = use(() => getStock(ticker), [ticker]); async function follow(): Promise { - if (state.stock === null) { + if (state === undefined || state.stock === null) { return; } @@ -37,6 +37,10 @@ export function StockDetails({ } return useReactive(() => { + if (state === undefined) { + return <>; + } + const { stock } = state; return ( diff --git a/demos/react-store/src/components/DataTable.tsx b/demos/react-store/src/components/DataTable.tsx index 29984879..2da7d463 100644 --- a/demos/react-store/src/components/DataTable.tsx +++ b/demos/react-store/src/components/DataTable.tsx @@ -1,20 +1,16 @@ -import { LOGGER, LogLevel } from "@starbeam/debug"; import { useProp, useReactive, useSetup } from "@starbeam/react"; import { Cell } from "@starbeam/universal"; -import { DevTools } from "@starbeamx/devtool"; import { Table } from "@starbeamx/store"; import type { FormEvent } from "react"; import { type Person, People } from "../lib/people.js"; -LOGGER.level = LogLevel.Debug; - export default function (props: { locale: string }): JSX.Element { const locale = useProp(props.locale, "props.locale"); const { people, append, filter, total, rows, table } = useSetup( (component) => { - component.attach(DevTools); + // component.attach(DevTools); const table = Table.create({ columns: ["name", "location"], diff --git a/demos/react-store/src/components/DateFormatter.tsx b/demos/react-store/src/components/DateFormatter.tsx index ba4dbfa4..28f0fb88 100644 --- a/demos/react-store/src/components/DateFormatter.tsx +++ b/demos/react-store/src/components/DateFormatter.tsx @@ -2,8 +2,9 @@ import { useSetup } from "@starbeam/react"; import { type ResourceBlueprint, Cell, - Reactive, + type Reactive, Resource, + readReactive, } from "@starbeam/universal"; import { @@ -50,7 +51,7 @@ export default function (props: { locale: string }): JSX.Element { -

    {date.current.formatted}

    +

    {date.current?.formatted}

    ); }; @@ -67,8 +68,6 @@ function Clock( date.current = new Date(); } - const reactiveLocale = Reactive.from(locale); - return Resource((resource) => { const interval = setInterval(() => { refresh(); @@ -81,7 +80,7 @@ function Clock( return { formatted: formatDate( date.current, - reactiveLocale.read(), + readReactive(locale), timeZone.read() ), refresh, diff --git a/demos/react/src/components/formatter/DateFormatter-v2.tsx b/demos/react/src/components/formatter/DateFormatter-v2.tsx index 931a1ced..5efce3bd 100644 --- a/demos/react/src/components/formatter/DateFormatter-v2.tsx +++ b/demos/react/src/components/formatter/DateFormatter-v2.tsx @@ -20,7 +20,7 @@ export default function DateFormatterStarbeam(): JSX.Element { -

    {date.current.formatted}

    +

    {date.current?.formatted}

    ); }; diff --git a/demos/react/src/components/formatter/DateFormatter-v3.tsx b/demos/react/src/components/formatter/DateFormatter-v3.tsx index 549d067e..c277dc03 100644 --- a/demos/react/src/components/formatter/DateFormatter-v3.tsx +++ b/demos/react/src/components/formatter/DateFormatter-v3.tsx @@ -52,7 +52,7 @@ export default function DateFormatterStarbeam(): JSX.Element { {selectBox} -

    {date.current.formatted}

    +

    {date.current?.formatted}

    ); }; diff --git a/demos/react/src/components/formatter/DateFormatterFinal.tsx b/demos/react/src/components/formatter/DateFormatterFinal.tsx index 9f7648ab..60280a2f 100644 --- a/demos/react/src/components/formatter/DateFormatterFinal.tsx +++ b/demos/react/src/components/formatter/DateFormatterFinal.tsx @@ -47,7 +47,7 @@ export default function DateFormatterStarbeam(props: { -

    {date.formatted}

    +

    {date?.formatted}

    ); } @@ -71,14 +71,6 @@ function Clock( clearInterval(interval); }); - return { - formatted: formatTime(date.now, { - timeZone: typeof timeZone === "string" ? timeZone : timeZone.read(), - locale: typeof locale === "string" ? locale : locale.read(), - }), - refresh, - }; - }).initial(() => { return { formatted: formatTime(date.now, { timeZone: typeof timeZone === "string" ? timeZone : timeZone.read(), @@ -87,6 +79,15 @@ function Clock( refresh, }; }); + // .initial(() => { + // return { + // formatted: formatTime(date.now, { + // timeZone: typeof timeZone === "string" ? timeZone : timeZone.read(), + // locale: typeof locale === "string" ? locale : locale.read(), + // }), + // refresh, + // }; + // }); } function formatTime( diff --git a/packages/preact/preact/src/resource.ts b/packages/preact/preact/src/resource.ts index 7b8d87d4..7a556112 100644 --- a/packages/preact/preact/src/resource.ts +++ b/packages/preact/preact/src/resource.ts @@ -7,18 +7,14 @@ import { useMemo } from "preact/hooks"; import { getCurrentComponent } from "./options.js"; -export function use( - blueprint: IntoResourceBlueprint -): ReadValue { +export function use(blueprint: IntoResourceBlueprint): T { return useMemo(() => { const owner = verified(getCurrentComponent(), isPresent); return resource.use(blueprint, { lifetime: owner }); }, []).current; } -export function service( - blueprint: IntoResourceBlueprint -): ReadValue { +export function service(blueprint: IntoResourceBlueprint): T { return useMemo(() => { return createService(blueprint); }, []).current; diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index ab240bd2..232e6233 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -1,4 +1,3 @@ -import { Message } from "@starbeam/debug"; import { RUNTIME } from "@starbeam/runtime"; import { isRendering } from "@starbeam/use-strict-lifecycle"; @@ -19,63 +18,63 @@ if (import.meta.env.DEV) { ...["Created: ", "Accessed: "].map((s) => s.length) ); - const message = Message([ - [ - ["ERROR", "color:#f00", "font-weight:bold"], - " ", - [ - "You read from a reactive value but you were not inside the `useReactive` hook.", - "color: #b00", - ], - ], - "", - [ - ["Created: ".padEnd(pad, "…"), "color:#666"], - " ", - [fullName, "color:#6a6"], - ], - // FIXME: frame.link() - // [ - // [" ".repeat(pad), "color:#666"], - // " ", - // [description.frame?.link() ?? "", "color:#6a6"], - // ], - // [ - // ["Accessed: ".padEnd(pad, "…"), "color:#666"], - // " ", - // [caller?.link() ?? "", "color:#6a6"], - // ], - "", - [ - [ - "This will prevent React from re-rendering when the reactive value changes.", - "color:#b00", - ], - ], - "", - [ - [ - "Make sure that you are inside a `useReactive` hook whenever you access reactive state.", - "color:#559", - ], - ], - "", - [ - [ - "You can wrap your entire component in `useReactive`, and return JSX to avoid this error. If you are also creating reactive cells in your component, you can use the `useSetup` hook to create cells and return JSX that reads from those cells.", - "color:#559", - ], - ], - "", - [ - [ - "You can also use the `starbeam` HOC to create a component that automatically wraps your the entire body of your component in `useSetup`.", - "color:#559", - ], - ], - ]); + // const message = Message([ + // [ + // ["ERROR", "color:#f00", "font-weight:bold"], + // " ", + // [ + // "You read from a reactive value but you were not inside the `useReactive` hook.", + // "color: #b00", + // ], + // ], + // "", + // [ + // ["Created: ".padEnd(pad, "…"), "color:#666"], + // " ", + // [fullName, "color:#6a6"], + // ], + // // FIXME: frame.link() + // // [ + // // [" ".repeat(pad), "color:#666"], + // // " ", + // // [description.frame?.link() ?? "", "color:#6a6"], + // // ], + // // [ + // // ["Accessed: ".padEnd(pad, "…"), "color:#666"], + // // " ", + // // [caller?.link() ?? "", "color:#6a6"], + // // ], + // "", + // [ + // [ + // "This will prevent React from re-rendering when the reactive value changes.", + // "color:#b00", + // ], + // ], + // "", + // [ + // [ + // "Make sure that you are inside a `useReactive` hook whenever you access reactive state.", + // "color:#559", + // ], + // ], + // "", + // [ + // [ + // "You can wrap your entire component in `useReactive`, and return JSX to avoid this error. If you are also creating reactive cells in your component, you can use the `useSetup` hook to create cells and return JSX that reads from those cells.", + // "color:#559", + // ], + // ], + // "", + // [ + // [ + // "You can also use the `starbeam` HOC to create a component that automatically wraps your the entire body of your component in `useSetup`.", + // "color:#559", + // ], + // ], + // ]); - console.warn(...message); + // console.warn(...message); // FIXME: caller.stack // if (caller) { diff --git a/packages/react/react/src/use-service.ts b/packages/react/react/src/use-service.ts index 4b7ba84b..2db43281 100644 --- a/packages/react/react/src/use-service.ts +++ b/packages/react/react/src/use-service.ts @@ -6,9 +6,7 @@ import { service } from "@starbeam/service"; import { ReactApp, useStarbeamApp } from "./context-provider.js"; import { useReactive } from "./use-reactive.js"; -export function useService( - blueprint: IntoResourceBlueprint -): ReadValue { +export function useService(blueprint: IntoResourceBlueprint): T { CONTEXT.app = ReactApp.instance(useStarbeamApp({ feature: "useService()" })); const instance = service(blueprint); diff --git a/packages/universal/core-utils/src/array.ts b/packages/universal/core-utils/src/array.ts index 5fd60ae5..08d062a5 100644 --- a/packages/universal/core-utils/src/array.ts +++ b/packages/universal/core-utils/src/array.ts @@ -39,10 +39,18 @@ export function mapPresentArray( return list.map(mapper) as PresentArray; } +export function mapIfPresent( + list: T[] | undefined | null, + mapper: (item: T, index: number) => U +): MutablePresentArray | undefined; +export function mapIfPresent( + list: readonly T[] | undefined | null, + mapper: (item: T, index: number) => U +): ReadonlyPresentArray | undefined; export function mapIfPresent( list: T[] | readonly T[] | undefined | null, mapper: (item: T, index: number) => U -): PresentArray | undefined { +): MutablePresentArray | ReadonlyPresentArray | undefined { if (list && isPresentArray(list)) { return mapPresentArray(list, mapper); } else { diff --git a/packages/universal/debug/src/setup.ts b/packages/universal/debug/src/setup.ts index a253edba..036f4dac 100644 --- a/packages/universal/debug/src/setup.ts +++ b/packages/universal/debug/src/setup.ts @@ -4,7 +4,7 @@ if ( ) { try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires - const buffer = require("buffer"); + const buffer = await import("buffer"); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access globalThis.Buffer = buffer.Buffer; } catch { diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 95e72725..4db2109a 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -1,3 +1,19 @@ +export type { Reactive } from "@starbeam/interfaces"; +export { + Cell, + type Equality, + Static, + Formula as PolledFormula, + CachedFormula as Formula, + Marker, + read as readReactive, +} from "@starbeam/reactive"; +export { + Resource, + type ResourceBlueprint, + type ResourceRun, + use, +} from "@starbeam/resource"; export { DEBUG_RENDERER } from "./src/debug-renderer.js"; export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; export { @@ -6,12 +22,7 @@ export { Variants, type VariantType, } from "./src/reactive-core/variants.js"; -export { Cell, type Equality, Static } from "@starbeam/reactive"; export { Wrap } from "@starbeam/reactive/src/primitives/delegate.js"; -export { - Resource, - type ResourceBlueprint, - type ResourceRun, - use, -} from "@starbeam/resource"; +export { Freshness } from "./src/reactive-core/higher-level/freshness.js"; + export { LIFETIME, PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; diff --git a/packages/x/devtool/index.tsx b/packages/x/devtool/index.tsx index 0595664f..222c5272 100644 --- a/packages/x/devtool/index.tsx +++ b/packages/x/devtool/index.tsx @@ -1,5 +1,4 @@ export * from "./src/log/log.js"; export type { UpdatePane } from "./src/log/pane.js"; -export type { DevtoolsOptions } from "./src/log/shared.js"; export * from "./src/log/tabs.js"; -export * from "./src/single/single-reactive.js"; +// export * from "./src/single/single-reactive.js"; diff --git a/packages/x/devtool/src/log/cell.tsx b/packages/x/devtool/src/log/cell.tsx index d028abd5..d180a20f 100644 --- a/packages/x/devtool/src/log/cell.tsx +++ b/packages/x/devtool/src/log/cell.tsx @@ -1,16 +1,21 @@ import "preact"; /** @jsxRuntime automatic @jsxImportSource preact */ -import type { - CellConsumeOperation, - CellUpdateOperation, -} from "@starbeam/debug"; -import type { Timestamp } from "@starbeam/interfaces/index.js"; +// import type { +// CellConsumeOperation, +// CellUpdateOperation, +// } from "@starbeam/debug"; +import type { Timestamp } from "@starbeam/interfaces"; import type { JSX } from "preact"; -import type { DevtoolsOptions } from "./shared.js"; +// import type { DevtoolsOptions } from "./shared.js"; import { LogLineFor } from "./ui.js"; +type FIXME = any; +type CellConsumeOperation = FIXME; +type DevtoolsOptions = FIXME; +type CellUpdateOperation = FIXME; + export function CellConsumeLine({ line, prev, diff --git a/packages/x/devtool/src/log/describe.tsx b/packages/x/devtool/src/log/describe.tsx index fbd9fc58..fa8abdcd 100644 --- a/packages/x/devtool/src/log/describe.tsx +++ b/packages/x/devtool/src/log/describe.tsx @@ -1,15 +1,13 @@ import "preact"; import { isPresentArray, isSingleItemArray } from "@starbeam/core-utils"; -/** @jsxRuntime automatic @jsxImportSource preact */ -import type { - DescriptionParts, - DetailsPart, - StackFrameDisplayOptions, -} from "@starbeam/interfaces/index.js"; import type { ComponentChildren, JSX } from "preact"; - -import type { DevtoolsOptions } from "./shared.js"; +/** @jsxRuntime automatic @jsxImportSource preact */ +type FIXME = any; +type DevtoolsOptions = FIXME; +type DescriptionParts = FIXME; +type StackFrameDisplayOptions = FIXME; +type DetailsPart = FIXME; export function DescribeLeaf({ leaf, @@ -200,7 +198,7 @@ export function Name({ } } default: - exhaustive(details); + exhaustive(details as never); } } diff --git a/packages/x/devtool/src/log/frame.tsx b/packages/x/devtool/src/log/frame.tsx index 755ee276..cfaccdb0 100644 --- a/packages/x/devtool/src/log/frame.tsx +++ b/packages/x/devtool/src/log/frame.tsx @@ -1,13 +1,16 @@ /** @jsxRuntime automatic @jsxImportSource preact */ -import type { FrameConsumeOperation } from "@starbeam/debug"; -import type { MutableInternals, Timestamp } from "@starbeam/interfaces/index.js"; -import { ReactiveInternals } from "@starbeam/runtime"; import type { JSX } from "preact"; import { DescribeLeaf } from "./describe.js"; -import type { DevtoolsOptions } from "./shared.js"; + import { LogLineFor } from "./ui.js"; +import type { CellTag, Timestamp } from "@starbeam/interfaces"; +import { logTag } from "@starbeam/debug"; + +type FIXME = any; +type FrameConsumeOperation = FIXME; +type DevtoolsOptions = FIXME; export function FrameConsumeLine({ line, @@ -21,7 +24,7 @@ export function FrameConsumeLine({ const at = line.at; const frame = line.for; console.log(line.diff); - ReactiveInternals.log(frame); + logTag(frame); const description = frame.description.parts; @@ -52,7 +55,7 @@ function List({ cells, change, }: { - cells: Set; + cells: Set; change: "add" | "remove"; }): JSX.Element | null { if (cells.size === EMPTY_SET) { @@ -63,7 +66,7 @@ function List({

    {change}

    {[...cells].map((cell) => ( - + ))}
    diff --git a/packages/x/devtool/src/log/log.tsx b/packages/x/devtool/src/log/log.tsx index bfb210b5..577abdd5 100644 --- a/packages/x/devtool/src/log/log.tsx +++ b/packages/x/devtool/src/log/log.tsx @@ -1,29 +1,32 @@ import "preact"; /** @jsxRuntime automatic @jsxImportSource preact */ -import type { DebugOperation } from "@starbeam/debug"; -import type { Timestamp } from "@starbeam/interfaces/index.js"; -import { TIMELINE } from "@starbeam/runtime"; import type { JSX } from "preact"; import { useMemo, useState } from "preact/hooks"; import { CellConsumeLine, CellUpdateLine } from "./cell.js"; import css from "./css/log.css?inline"; import { FrameConsumeLine } from "./frame.js"; -import type {UpdatePane} from "./pane.js"; +import type { UpdatePane } from "./pane.js"; import { Pane, UiPane } from "./pane.js"; -import type { DevtoolsOptions } from "./shared.js"; import { LogLine } from "./ui.js"; +import type { Timestamp } from "@starbeam/interfaces"; + +type FIXME = any; +type DevtoolsOptions = FIXME; +type DebugOperation = FIXME; +type ATTACH = FIXME; +declare const ATTACH: ATTACH; export function DevtoolsLog({ - options = {} + options = {}, }: { options?: DevtoolsOptions; }): JSX.Element { const { filter = { type: "all" } } = options; const listener = useMemo(() => { - const listener = TIMELINE.attach( + const listener = ATTACH.attach( () => { setLogs((prev) => [...listener.flush().reverse(), ...prev]); }, @@ -80,6 +83,9 @@ function LogOperation({ case "mutation": return Unimplemented mutation log; + + default: + throw Error(`Unimplemented: this switch should be exhaustive`); } } diff --git a/packages/x/devtool/src/log/shared.ts b/packages/x/devtool/src/log/shared.ts index 9e732924..4a28c081 100644 --- a/packages/x/devtool/src/log/shared.ts +++ b/packages/x/devtool/src/log/shared.ts @@ -1,9 +1,9 @@ -import type { DebugFilter } from "@starbeam/debug"; -import type { StackFrameDisplayOptions } from "@starbeam/interfaces"; +// import type { DebugFilter } from "@starbeam/debug"; +// import type { StackFrameDisplayOptions } from "@starbeam/interfaces"; -export type DevtoolsLineOptions = StackFrameDisplayOptions; +// export type DevtoolsLineOptions = StackFrameDisplayOptions; -export interface DevtoolsOptions extends DevtoolsLineOptions { - filter?: DebugFilter; - internals?: boolean; -} +// export interface DevtoolsOptions extends DevtoolsLineOptions { +// filter?: DebugFilter; +// internals?: boolean; +// } diff --git a/packages/x/devtool/src/log/tabs.tsx b/packages/x/devtool/src/log/tabs.tsx index fa472326..409527b2 100644 --- a/packages/x/devtool/src/log/tabs.tsx +++ b/packages/x/devtool/src/log/tabs.tsx @@ -4,7 +4,9 @@ import type { JSX } from "preact"; import css from "./css/pane.css?inline"; import { type UpdatePane, Pane, UiPane } from "./pane.js"; -import type { DevtoolsOptions } from "./shared.js"; + +type FIXME = any; +type DevtoolsOptions = FIXME; export function TabsPane( into: Element, diff --git a/packages/x/devtool/src/log/ui.tsx b/packages/x/devtool/src/log/ui.tsx index fd7b3434..055ce89c 100644 --- a/packages/x/devtool/src/log/ui.tsx +++ b/packages/x/devtool/src/log/ui.tsx @@ -1,12 +1,14 @@ /** @jsxRuntime automatic @jsxImportSource preact */ -import type { DescriptionParts } from "@starbeam/debug"; import { Timestamp } from "@starbeam/runtime"; import type { ComponentChildren, JSX } from "preact"; import { useState } from "preact/hooks"; import { DescribeLeaf, Frame, Internal } from "./describe.js"; -import type { DevtoolsOptions } from "./shared.js"; + +type FIXME = any; +type DevtoolsOptions = FIXME; +type DescriptionParts = FIXME; function Line({ timestamp, diff --git a/packages/x/devtool/src/single/single-reactive.tsx b/packages/x/devtool/src/single/single-reactive.tsx.todo similarity index 89% rename from packages/x/devtool/src/single/single-reactive.tsx rename to packages/x/devtool/src/single/single-reactive.tsx.todo index 6281f9bf..92935164 100644 --- a/packages/x/devtool/src/single/single-reactive.tsx +++ b/packages/x/devtool/src/single/single-reactive.tsx.todo @@ -1,18 +1,15 @@ import "./devtool.css"; -import type { - DebugListener, - DebugOperation, - Description, -} from "@starbeam/debug"; -import type { CellTag } from "@starbeam/interfaces"; -import type { Tagged } from "@starbeam/runtime"; -import { TIMELINE } from "@starbeam/runtime"; +import type { CellTag, Description } from "@starbeam/interfaces"; +import { PUBLIC_TIMELINE, RUNTIME, type Tagged } from "@starbeam/runtime"; import { getTag } from "@starbeam/tags"; import { isPresent, verified } from "@starbeam/verify"; import type { JSX } from "preact"; import { render } from "preact"; +type FIXME = any; +type DebugOperation = FIXME; + export function DevtoolsFor(props: { reactive: Tagged; log: DebugOperation[]; @@ -41,12 +38,12 @@ export function DevtoolsFor(props: {
  • description - {taggedDescription(props.reactive).fullName} + {RUNTIME.debug?.describeTagged(props.reactive)}
  • last updated - {String(TIMELINE.now)} + {String(PUBLIC_TIMELINE.now)}
  • Dependencies

    @@ -83,7 +80,7 @@ function Dependency({ const specified = {description.fullName}; function displayLink(): void { - if (description.fullName) { + if ( description) { console.log( "%c%s @ %s", "color:red", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94cc5461..0130fca2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -173,9 +173,18 @@ importers: '@starbeam/collections': specifier: workspace:^ version: link:../../packages/universal/collections + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../packages/universal/interfaces '@starbeam/preact': specifier: workspace:^ version: link:../../packages/preact/preact + '@starbeam/reactive': + specifier: workspace:^ + version: link:../../packages/universal/reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../../packages/universal/resource '@starbeam/universal': specifier: workspace:^ version: link:../../packages/universal/universal @@ -287,12 +296,18 @@ importers: '@starbeam/debug': specifier: workspace:^ version: link:../../packages/universal/debug + '@starbeam/interfaces': + specifier: workspace:^ + version: link:../../packages/universal/interfaces '@starbeam/react': specifier: workspace:^ version: link:../../packages/react/react '@starbeam/reactive': specifier: workspace:^ version: link:../../packages/universal/reactive + '@starbeam/resource': + specifier: workspace:^ + version: link:../../packages/universal/resource '@starbeam/universal': specifier: workspace:^ version: link:../../packages/universal/universal @@ -1789,6 +1804,9 @@ importers: '@starbeam-dev/build-support': specifier: workspace:* version: link:../build + '@types/ansicolor': + specifier: workspace:^ + version: link:../../@types/ansicolor '@types/node': specifier: 18.15.11 version: 18.15.11 diff --git a/workspace/package/src/query/filters.ts b/workspace/package/src/query/filters.ts index 1d8c39ad..782ed19d 100644 --- a/workspace/package/src/query/filters.ts +++ b/workspace/package/src/query/filters.ts @@ -4,12 +4,12 @@ import { isSingleItemArray, } from "@starbeam/core-utils"; import type { Reporter } from "@starbeam-workspace/reporter"; -import type { UnionClass } from "@starbeam-workspace/shared/src/type-magic.js"; import util from "util"; import type { Package } from "../package"; import { StarbeamType } from "../unions.js"; import { ParseError } from "./query"; +import type { UnionClass } from "@starbeam-workspace/shared"; export class SingleFilter implements Filter { readonly type = "ok"; diff --git a/workspace/reporter/package.json b/workspace/reporter/package.json index c8b4a910..3ee4ab88 100644 --- a/workspace/reporter/package.json +++ b/workspace/reporter/package.json @@ -42,6 +42,8 @@ }, "devDependencies": { "@starbeam-dev/build-support": "workspace:*", + "@starbeam-workspace/shared": "workspace:*", + "@types/ansicolor": "workspace:^", "@types/node": "^18.11.9", "@types/shell-escape-tag": "workspace:^", "@types/shell-split": "workspace:^", diff --git a/workspace/reporter/src/table.ts b/workspace/reporter/src/table.ts index 941622d2..82457ee3 100644 --- a/workspace/reporter/src/table.ts +++ b/workspace/reporter/src/table.ts @@ -1,8 +1,4 @@ -import { - isPresent, - mapIfPresent, - objectHasKeys, -} from "@starbeam/core-utils"; +import { isPresent, mapIfPresent, objectHasKeys } from "@starbeam/core-utils"; import { DisplayStruct } from "@starbeam-workspace/shared"; import Table from "cli-table3"; @@ -106,13 +102,13 @@ class Columns { } headers(state: LoggerState): string[] | undefined { - return mapIfPresent( - this.#columns, - (column) => column.header(state) ?? "" - ); + return mapIfPresent(this.#columns, (column) => column.header(state) ?? ""); } - columnWidths(rows: Cell[][], state: LoggerState): number[] | undefined { + columnWidths( + rows: Cell[][], + state: LoggerState + ): readonly number[] | undefined { return mapIfPresent(this.#columns, (column, index) => column.maxWidth(rows.map((row) => row[index]).filter(isPresent), state) ); diff --git a/workspace/shared/index.ts b/workspace/shared/index.ts index de9cc6b3..96741025 100644 --- a/workspace/shared/index.ts +++ b/workspace/shared/index.ts @@ -12,5 +12,6 @@ export type { OkRecord, OkResult, UnionInstance, + UnionClass, } from "./src/type-magic.js"; export { PresentArray, Result, Union } from "./src/type-magic.js"; From 75cf20d5e3c51e84df2fb50e40e55c5d16876f53 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 14:11:46 -0700 Subject: [PATCH 39/46] Fix ci:types --- .../debug/src/description/debug/description.ts | 4 ++-- .../universal/debug/src/description/debug/index.ts | 4 ++-- packages/universal/debug/src/description/prod.ts | 4 ++-- .../universal/interfaces/src/debug/debug-runtime.ts | 4 ++-- packages/universal/interfaces/src/debug/description.ts | 2 +- packages/universal/reactive/src/runtime.ts | 4 +--- packages/universal/runtime/src/define.ts | 4 ++-- workspace/build/index.d.ts | 2 +- workspace/build/src/config.d.ts | 10 ++++++---- workspace/build/src/config.js | 8 ++++---- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/universal/debug/src/description/debug/description.ts b/packages/universal/debug/src/description/debug/description.ts index 9a0fbf9f..1da54d58 100644 --- a/packages/universal/debug/src/description/debug/description.ts +++ b/packages/universal/debug/src/description/debug/description.ts @@ -4,7 +4,7 @@ import type { CallStack, Description as IDescription, DescriptionDetails, - DescriptionRuntime, + DescFn, Nesting, ReactiveId, ReactiveType, @@ -148,4 +148,4 @@ export const Desc = (( caller, }); return desc; -}) satisfies DescriptionRuntime; +}) satisfies DescFn; diff --git a/packages/universal/debug/src/description/debug/index.ts b/packages/universal/debug/src/description/debug/index.ts index ccb44dff..ac588f17 100644 --- a/packages/universal/debug/src/description/debug/index.ts +++ b/packages/universal/debug/src/description/debug/index.ts @@ -1,4 +1,4 @@ -import type { DescriptionRuntime } from "@starbeam/interfaces"; +import type { DescFn } from "@starbeam/interfaces"; import { Desc as desc } from "./description.js"; -export default desc satisfies DescriptionRuntime; +export default desc satisfies DescFn; diff --git a/packages/universal/debug/src/description/prod.ts b/packages/universal/debug/src/description/prod.ts index 7aed9aaa..1e8863ae 100644 --- a/packages/universal/debug/src/description/prod.ts +++ b/packages/universal/debug/src/description/prod.ts @@ -1,3 +1,3 @@ -import type { DescriptionRuntime } from "@starbeam/interfaces"; +import type { DescFn } from "@starbeam/interfaces"; -export default (() => undefined) satisfies DescriptionRuntime; +export default (() => undefined) satisfies DescFn; diff --git a/packages/universal/interfaces/src/debug/debug-runtime.ts b/packages/universal/interfaces/src/debug/debug-runtime.ts index e93f5a88..018218a9 100644 --- a/packages/universal/interfaces/src/debug/debug-runtime.ts +++ b/packages/universal/interfaces/src/debug/debug-runtime.ts @@ -1,6 +1,6 @@ import type { Tag, Tagged } from "../protocol.js"; import type { CallerStackFn, CallStack } from "./call-stack.js"; -import type { DescriptionDetails, DescriptionRuntime } from "./description.js"; +import type { DescriptionDetails, DescFn } from "./description.js"; export interface DebugRuntime { getUserFacing: ( @@ -19,5 +19,5 @@ export interface DebugRuntime { ) => void; readonly callerStack: CallerStackFn; - readonly desc: DescriptionRuntime; + readonly desc: DescFn; } diff --git a/packages/universal/interfaces/src/debug/description.ts b/packages/universal/interfaces/src/debug/description.ts index 8c4b722a..d52584da 100644 --- a/packages/universal/interfaces/src/debug/description.ts +++ b/packages/universal/interfaces/src/debug/description.ts @@ -9,7 +9,7 @@ export type ReactiveType = | "collection" | "collection:item"; -export type DescriptionRuntime = ( +export type DescFn = ( type: ReactiveType, specified?: string | Description | undefined, // FIXME: speculative inference strategy: if you have a call stack, use the diff --git a/packages/universal/reactive/src/runtime.ts b/packages/universal/reactive/src/runtime.ts index ead0523e..dfb7e83d 100644 --- a/packages/universal/reactive/src/runtime.ts +++ b/packages/universal/reactive/src/runtime.ts @@ -2,6 +2,7 @@ import type { AutotrackingRuntime, CallerStackFn, DebugRuntime, + DescFn, DescriptionDetails, Runtime, SubscriptionRuntime, @@ -30,9 +31,6 @@ function getRuntime(): Runtime { export const UNKNOWN_REACTIVE_VALUE = "{unknown reactive value}"; -type DescFn = - typeof import("../../debug/src/description/debug/description.js")["Desc"]; - class RuntimeImpl implements Runtime { get Desc(): DescFn | undefined { return (getRuntime().debug?.desc as DescFn) ?? undefined; diff --git a/packages/universal/runtime/src/define.ts b/packages/universal/runtime/src/define.ts index 24b34ce7..20ff7c85 100644 --- a/packages/universal/runtime/src/define.ts +++ b/packages/universal/runtime/src/define.ts @@ -3,7 +3,7 @@ import type { AutotrackingRuntime, CallerStackFn, DebugRuntime, - DescriptionRuntime, + DescFn, Runtime as IRuntime, SubscriptionRuntime, } from "@starbeam/interfaces"; @@ -53,7 +53,7 @@ class Runtime implements IRuntime { this.#debug = debug; } - get Desc(): DescriptionRuntime | undefined { + get Desc(): DescFn | undefined { return this.debug?.desc; } diff --git a/workspace/build/index.d.ts b/workspace/build/index.d.ts index c56239a6..6916a5eb 100644 --- a/workspace/build/index.d.ts +++ b/workspace/build/index.d.ts @@ -1,7 +1,7 @@ export { type PackageInfo, type PackageJSON, - type ViteExport, + type ViteConfig as ViteExport, Package, } from "./src/config.js"; export { default as importMeta } from "./src/import-meta.js"; diff --git a/workspace/build/src/config.d.ts b/workspace/build/src/config.d.ts index 5738da07..c2eec0d7 100644 --- a/workspace/build/src/config.d.ts +++ b/workspace/build/src/config.d.ts @@ -63,9 +63,11 @@ export type ExternalOption = | [ExternalOperator, SimpleExternal]; export type RollupExport = rollup.RollupOptions | rollup.RollupOptions[]; -export type ViteExport = - | Pick - | Promise; +export type ViteConfig = Pick< + vite.UserConfig, + "plugins" | "esbuild" | "optimizeDeps" | "build" +>; +export type ViteExport = ViteConfig | Promise; import type { FlatConfigItem } from "./eslint-flat.js.js.js"; @@ -75,7 +77,7 @@ export class Package { static root(meta: ImportMeta): string; static at(meta: ImportMeta | string): Package | undefined; static config(meta: ImportMeta | string): RollupExport; - static viteConfig(meta: ImportMeta | string): ViteExport; + static viteConfig(meta: ImportMeta | string): ViteConfig; static eslintConfig(meta: ImportMeta | string): ESLintExport; readonly entry: Record; diff --git a/workspace/build/src/config.js b/workspace/build/src/config.js index 7b45af01..0d07c1bf 100644 --- a/workspace/build/src/config.js +++ b/workspace/build/src/config.js @@ -33,7 +33,7 @@ const { /** @typedef {import("rollup").RollupOptions} RollupOptions */ /** * @typedef {import("./config.js").ESLintExport} ESLintExport - * @typedef {import("./config.js").ViteExport} ViteExport + * @typedef {import("./config.js").ViteConfig} ViteConfig * @typedef {import("./config.js").StarbeamKey} StarbeamKey * @typedef {import("./config.js").JsonValue} JsonValue * @typedef {import("./config.js").JsonObject} JsonObject @@ -252,7 +252,7 @@ export class Package { /** * @param {ImportMeta | string} meta - * @returns {Promise} + * @returns {Promise} */ static async viteConfig(meta) { const pkg = Package.at(meta); @@ -312,7 +312,7 @@ export class Package { } /** - * @returns {Promise} + * @returns {Promise} */ async #viteConfig() { return viteConfig({ @@ -491,7 +491,7 @@ function mapExternal(inline) { } /** - * @param {import("./config.js").ViteExport} config + * @param {import("./config.js").ViteConfig} config */ async function viteConfig(config) { return config; From ca8a5e304b86da07ad14a710e1d443d9d44eacf8 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 14:55:43 -0700 Subject: [PATCH 40/46] Fix lints --- @types/ansicolor/package.json | 2 +- .../preact-hello-world/src/components/App.tsx | 2 +- demos/preact-hello-world/src/index.tsx | 4 +- demos/preact/package.json | 2 +- .../components/formatter/DateFormatter-v2.tsx | 2 +- .../components/formatter/DateFormatter-v3.tsx | 4 +- .../formatter/DateFormatterFinal.tsx | 6 +- demos/preact/src/index.tsx | 4 +- demos/react-jsnation/index.ts | 1 + .../src/components/DataTable.tsx | 2 +- .../src/components/DataTableFinished.tsx | 2 +- .../src/components/DateFormatter.tsx | 6 +- demos/react-jsnation/tests/package.json | 4 +- demos/react-lite-query/src/App.tsx | 4 +- demos/react-lite-query/src/lib/fetch.ts | 2 +- demos/react-query/src/components/App.tsx | 2 +- demos/react-query/src/lib/query.ts | 2 +- demos/react-query/src/lib/use-query.ts | 2 +- demos/react-stock-ticker/src/lib/api/api.ts | 1 + .../react-store/src/components/DataTable.tsx | 92 +++++++++---------- .../src/components/DateFormatter.tsx | 4 +- .../components/formatter/DateFormatter-v3.tsx | 4 +- .../formatter/DateFormatterFinal.tsx | 2 +- .../preact-testing-utils/src/testing.ts | 4 +- .../preact-utils/src/internals/elements.ts | 1 + .../preact-utils/src/internals/vnode.ts | 6 +- packages/preact/preact/src/resource.ts | 5 +- .../preact/preact/tests/support/testing.ts | 4 +- packages/react/react/src/debug/warnings.ts | 4 +- packages/react/react/src/element.ts | 2 +- .../react/react/src/use-component-instance.ts | 7 +- packages/react/react/src/use-service.ts | 3 +- packages/react/test-utils/index.ts | 2 +- packages/react/test-utils/src/dom.ts | 6 +- packages/react/test-utils/src/modes.ts | 10 +- .../src/description/debug/description.ts | 2 +- .../debug/src/description/debug/index.ts | 1 + packages/universal/debug/src/setup.ts | 2 - packages/universal/interfaces/index.ts | 7 +- .../interfaces/src/debug/debug-runtime.ts | 2 +- packages/universal/reactive/src/utils.ts | 2 +- .../universal/reactive/tests/cell.spec.ts | 2 +- .../universal/reactive/tests/tsconfig.json | 12 +++ packages/universal/universal/index.ts | 25 +++-- .../universal/verify/src/assertions/basic.ts | 4 +- packages/x/devtool/src/log/cell.tsx | 3 + packages/x/devtool/src/log/describe.tsx | 6 ++ packages/x/devtool/src/log/frame.tsx | 9 +- packages/x/devtool/src/log/log.tsx | 8 +- packages/x/devtool/src/log/tabs.tsx | 4 +- packages/x/devtool/src/log/ui.tsx | 3 + packages/x/store/index.ts | 2 +- workspace/build/index.d.ts | 2 +- workspace/build/src/config.js | 4 +- workspace/eslint/src/base.js | 3 +- workspace/eslint/src/esm.js | 3 +- workspace/package/index.ts | 4 +- workspace/package/src/package.ts | 7 +- workspace/package/src/packages.ts | 2 +- workspace/package/src/query/filters.ts | 2 +- workspace/package/src/unions.ts | 4 +- workspace/reporter/index.ts | 2 +- workspace/reporter/src/fancy-header.ts | 2 +- workspace/reporter/src/format.ts | 2 +- workspace/reporter/src/log.ts | 6 +- workspace/reporter/src/logger.ts | 2 +- workspace/reporter/src/reporter.ts | 20 ++-- workspace/reporter/src/styles.ts | 2 +- workspace/reporter/src/table.ts | 2 +- workspace/scripts/src/ci.ts | 2 +- workspace/scripts/src/clean.ts | 3 +- .../src/support/commands/build-command.ts | 6 +- .../src/support/commands/dev-command.ts | 4 +- .../src/support/commands/query-command.ts | 18 ++-- workspace/scripts/src/support/scripts.ts | 3 +- .../support/template/update-package-json.ts | 2 +- .../src/support/template/update-package.ts | 3 +- workspace/scripts/src/test.ts | 5 +- workspace/shared/index.ts | 2 +- workspace/test-utils/index.ts | 2 +- workspace/test-utils/src/vitest.ts | 1 + workspace/workspace/src/checks.ts | 2 +- workspace/workspace/src/workspace.ts | 18 ++-- 83 files changed, 237 insertions(+), 207 deletions(-) create mode 100644 packages/universal/reactive/tests/tsconfig.json diff --git a/@types/ansicolor/package.json b/@types/ansicolor/package.json index 20259fc5..80fb7417 100644 --- a/@types/ansicolor/package.json +++ b/@types/ansicolor/package.json @@ -1,8 +1,8 @@ { "private": true, "name": "@types/ansicolor", - "type":"module", "version": "1.0.0", + "type": "module", "types": "index.d.ts", "exports": { ".": { diff --git a/demos/preact-hello-world/src/components/App.tsx b/demos/preact-hello-world/src/components/App.tsx index e23c7cc4..b40b6b46 100644 --- a/demos/preact-hello-world/src/components/App.tsx +++ b/demos/preact-hello-world/src/components/App.tsx @@ -1,4 +1,4 @@ -import { create, createCell, service, use } from "@starbeam/preact"; +import { createCell, service, use } from "@starbeam/preact"; import type { ResourceBlueprint } from "@starbeam/universal"; import { Cell, Resource } from "@starbeam/universal"; import type { JSX } from "preact"; diff --git a/demos/preact-hello-world/src/index.tsx b/demos/preact-hello-world/src/index.tsx index 806854ed..c86e2d8e 100644 --- a/demos/preact-hello-world/src/index.tsx +++ b/demos/preact-hello-world/src/index.tsx @@ -3,10 +3,10 @@ import "preact/hooks"; import { setup } from "@starbeam/preact"; import { options, render } from "preact"; -setup(options); - import App from "./components/App.jsx"; +setup(options); + const container = document.querySelector("#root"); if (!container) { diff --git a/demos/preact/package.json b/demos/preact/package.json index 006cbe22..cefc86b9 100644 --- a/demos/preact/package.json +++ b/demos/preact/package.json @@ -40,8 +40,8 @@ "@starbeam/interfaces": "workspace:^", "@starbeam/preact": "workspace:^", "@starbeam/reactive": "workspace:^", + "@starbeam/resource": "workspace:^", "@starbeam/universal": "workspace:^", - "@starbeam/resource":"workspace:^", "preact": "^10.11.3", "purecss": "^3.0.0" }, diff --git a/demos/preact/src/components/formatter/DateFormatter-v2.tsx b/demos/preact/src/components/formatter/DateFormatter-v2.tsx index f6d92705..bd09c777 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v2.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v2.tsx @@ -1,6 +1,6 @@ import js from "@starbeam/collections"; import { use } from "@starbeam/preact"; -import { type ResourceBlueprint, Resource, Static } from "@starbeam/universal"; +import { Resource, type ResourceBlueprint, Static } from "@starbeam/universal"; import type { JSX } from "preact"; import { formatLocale, SYSTEM_LOCALE, SYSTEM_TZ } from "../intl.js"; diff --git a/demos/preact/src/components/formatter/DateFormatter-v3.tsx b/demos/preact/src/components/formatter/DateFormatter-v3.tsx index 65f6f91b..74e7866c 100644 --- a/demos/preact/src/components/formatter/DateFormatter-v3.tsx +++ b/demos/preact/src/components/formatter/DateFormatter-v3.tsx @@ -1,11 +1,11 @@ import js from "@starbeam/collections"; -import { create, use } from "@starbeam/preact"; import type { Reactive } from "@starbeam/interfaces"; +import { create, use } from "@starbeam/preact"; import { Cell, Resource, - Static, type ResourceBlueprint, + Static, } from "@starbeam/universal"; import type { JSX } from "preact"; diff --git a/demos/preact/src/components/formatter/DateFormatterFinal.tsx b/demos/preact/src/components/formatter/DateFormatterFinal.tsx index 9eebb880..dbb49568 100644 --- a/demos/preact/src/components/formatter/DateFormatterFinal.tsx +++ b/demos/preact/src/components/formatter/DateFormatterFinal.tsx @@ -1,5 +1,8 @@ import js from "@starbeam/collections"; +import type { Reactive } from "@starbeam/interfaces"; import { create, use } from "@starbeam/preact"; +import { Cell } from "@starbeam/reactive"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; import type { JSX } from "preact/jsx-runtime"; import { @@ -9,9 +12,6 @@ import { TIME_ZONES, timeZoneName, } from "../intl.js"; -import { Cell } from "@starbeam/reactive"; -import type { Reactive } from "@starbeam/interfaces"; -import { Resource, type ResourceBlueprint } from "@starbeam/resource"; export default function DateFormatterStarbeam(props: { locale: string; diff --git a/demos/preact/src/index.tsx b/demos/preact/src/index.tsx index 5b708491..0d9d3595 100644 --- a/demos/preact/src/index.tsx +++ b/demos/preact/src/index.tsx @@ -1,10 +1,10 @@ import { setup } from "@starbeam/preact"; import { options, render } from "preact"; -setup(options); - import App from "./components/App.jsx"; +setup(options); + const container = document.querySelector("#root"); if (!container) { diff --git a/demos/react-jsnation/index.ts b/demos/react-jsnation/index.ts index 17181124..d415da78 100644 --- a/demos/react-jsnation/index.ts +++ b/demos/react-jsnation/index.ts @@ -1,2 +1,3 @@ import App from "./src/components/App"; + export { App }; diff --git a/demos/react-jsnation/src/components/DataTable.tsx b/demos/react-jsnation/src/components/DataTable.tsx index 7e4d25c5..f8b77fea 100644 --- a/demos/react-jsnation/src/components/DataTable.tsx +++ b/demos/react-jsnation/src/components/DataTable.tsx @@ -1,6 +1,6 @@ import { useProp, useReactive, useSetup } from "@starbeam/react"; +import { CachedFormula as Formula, Cell } from "@starbeam/reactive"; import type { FormEvent } from "react"; -import { Cell, CachedFormula as Formula } from "@starbeam/reactive"; import { People, type Person } from "../lib/people.js"; import { type Row, Table } from "../lib/table.js"; diff --git a/demos/react-jsnation/src/components/DataTableFinished.tsx b/demos/react-jsnation/src/components/DataTableFinished.tsx index 0150b1cc..89c2bcc3 100644 --- a/demos/react-jsnation/src/components/DataTableFinished.tsx +++ b/demos/react-jsnation/src/components/DataTableFinished.tsx @@ -2,7 +2,7 @@ import { useSetup } from "@starbeam/react"; import { Cell } from "@starbeam/universal"; import type { FormEvent } from "react"; -import { type Person, People } from "../lib/people.js"; +import { People, type Person } from "../lib/people.js"; import { Table } from "../lib/table.js"; import { SYSTEM_LOCALE } from "./intl.js"; diff --git a/demos/react-jsnation/src/components/DateFormatter.tsx b/demos/react-jsnation/src/components/DateFormatter.tsx index 375d2155..6b2a243e 100644 --- a/demos/react-jsnation/src/components/DateFormatter.tsx +++ b/demos/react-jsnation/src/components/DateFormatter.tsx @@ -1,4 +1,7 @@ +import type { Reactive } from "@starbeam/interfaces"; import { useProp, useSetup } from "@starbeam/react"; +import { Cell } from "@starbeam/reactive"; +import { Resource, type ResourceBlueprint } from "@starbeam/resource"; import { formatLocale, @@ -7,9 +10,6 @@ import { TIME_ZONES, timeZoneName, } from "./intl.js"; -import type { Reactive } from "@starbeam/interfaces"; -import { Resource, type ResourceBlueprint } from "@starbeam/resource"; -import { Cell } from "@starbeam/reactive"; export default function (props: { locale: string }): JSX.Element { const locale = useProp(props.locale); diff --git a/demos/react-jsnation/tests/package.json b/demos/react-jsnation/tests/package.json index 842e5bc7..ff1e8e5e 100644 --- a/demos/react-jsnation/tests/package.json +++ b/demos/react-jsnation/tests/package.json @@ -22,7 +22,7 @@ }, "devDependencies": { "@testing-library/react": "^13.4.0", - "jsdom": "^21.1.1", - "@types/react": "^18.0.26" + "@types/react": "^18.0.26", + "jsdom": "^21.1.1" } } diff --git a/demos/react-lite-query/src/App.tsx b/demos/react-lite-query/src/App.tsx index 1fcec8b2..434d700c 100644 --- a/demos/react-lite-query/src/App.tsx +++ b/demos/react-lite-query/src/App.tsx @@ -1,12 +1,12 @@ import "./App.css"; -import { type UpdatePane, TabsPane } from "@starbeamx/devtool"; +import { TabsPane, type UpdatePane } from "@starbeamx/devtool"; import { Axios } from "axios"; import { useEffect, useRef } from "react"; import useQuery from "./lib/use-query.js"; -type FIXME = any; +type FIXME = never; type DevtoolsOptions = FIXME; export default function App(): JSX.Element { diff --git a/demos/react-lite-query/src/lib/fetch.ts b/demos/react-lite-query/src/lib/fetch.ts index 528548a7..52b9de0f 100644 --- a/demos/react-lite-query/src/lib/fetch.ts +++ b/demos/react-lite-query/src/lib/fetch.ts @@ -1,5 +1,5 @@ import { reactive } from "@starbeam/collections"; -import type { CallStack, Description } from "@starbeam/interfaces"; +import type { Description } from "@starbeam/interfaces"; import { RUNTIME } from "@starbeam/runtime"; import { Cell } from "@starbeam/universal"; import { isPresent, verified } from "@starbeam/verify"; diff --git a/demos/react-query/src/components/App.tsx b/demos/react-query/src/components/App.tsx index 0152cbb0..86e0aa1f 100644 --- a/demos/react-query/src/components/App.tsx +++ b/demos/react-query/src/components/App.tsx @@ -3,7 +3,7 @@ import "@shopify/polaris/build/esm/styles.css"; import { default as axios } from "axios"; import { StrictMode } from "react"; -import { type QueryResult, QUERY_CACHE } from "../lib/query.js"; +import { QUERY_CACHE, type QueryResult } from "../lib/query.js"; import { useQuery } from "../lib/use-query.js"; import type { Todo } from "./api.js"; import { diff --git a/demos/react-query/src/lib/query.ts b/demos/react-query/src/lib/query.ts index cab2d187..7bfda573 100644 --- a/demos/react-query/src/lib/query.ts +++ b/demos/react-query/src/lib/query.ts @@ -1,5 +1,5 @@ import { reactive } from "@starbeam/collections"; -import { Cell, Freshness, Marker } from "@starbeam/universal"; +import { Cell, Freshness } from "@starbeam/universal"; import { CanceledError } from "axios"; import { type Serializable, serialize } from "./key.js"; diff --git a/demos/react-query/src/lib/use-query.ts b/demos/react-query/src/lib/use-query.ts index 0f00c25e..711ce475 100644 --- a/demos/react-query/src/lib/use-query.ts +++ b/demos/react-query/src/lib/use-query.ts @@ -1,7 +1,7 @@ import { useSetup } from "@starbeam/react"; import type { Serializable } from "./key.js"; -import { type QueryFunction, type QueryResult, QUERY_CACHE } from "./query.js"; +import { QUERY_CACHE, type QueryFunction, type QueryResult } from "./query.js"; export function useQuery( key: Serializable, diff --git a/demos/react-stock-ticker/src/lib/api/api.ts b/demos/react-stock-ticker/src/lib/api/api.ts index dcf0e4b8..16bef854 100644 --- a/demos/react-stock-ticker/src/lib/api/api.ts +++ b/demos/react-stock-ticker/src/lib/api/api.ts @@ -1,6 +1,7 @@ import { STOCK_API_TOKEN } from "../env.js"; import { yesterday } from "../formatting.js"; import type { Stock } from "./interfaces.js"; + export const STOCK_API_PATH = "https://api.polygon.io"; const SearchTickerPath = `${STOCK_API_PATH}/v3/reference/tickers`; diff --git a/demos/react-store/src/components/DataTable.tsx b/demos/react-store/src/components/DataTable.tsx index 2da7d463..3910fe50 100644 --- a/demos/react-store/src/components/DataTable.tsx +++ b/demos/react-store/src/components/DataTable.tsx @@ -3,70 +3,68 @@ import { Cell } from "@starbeam/universal"; import { Table } from "@starbeamx/store"; import type { FormEvent } from "react"; -import { type Person, People } from "../lib/people.js"; +import { People, type Person } from "../lib/people.js"; export default function (props: { locale: string }): JSX.Element { const locale = useProp(props.locale, "props.locale"); - const { people, append, filter, total, rows, table } = useSetup( - (component) => { - // component.attach(DevTools); + const { people, append, filter, total, rows, table } = useSetup(() => { + // component.attach(DevTools); - const table = Table.create({ - columns: ["name", "location"], - name: "people", - }); + const table = Table.create({ + columns: ["name", "location"], + name: "people", + }); - table.append({ name: "Tom Dale", location: "NYC" }); - table.append({ name: "Chirag Patel", location: "NYC" }); - table.append({ name: "Yehuda Katz", location: "Portland" }); - table.append({ name: "Ärne Ärni", location: "Germany" }); + table.append({ name: "Tom Dale", location: "NYC" }); + table.append({ name: "Chirag Patel", location: "NYC" }); + table.append({ name: "Yehuda Katz", location: "Portland" }); + table.append({ name: "Ärne Ärni", location: "Germany" }); - const people = new People(table); + const people = new People(table); - function append(e: FormEvent): void { - e.preventDefault(); + function append(e: FormEvent): void { + e.preventDefault(); - const form = e.currentTarget; - const data = Object.fromEntries(new FormData(form)) as { - name: string; - location: string; - }; + const form = e.currentTarget; + const data = Object.fromEntries(new FormData(form)) as { + name: string; + location: string; + }; - table.append(data); - form.reset(); - } + table.append(data); + form.reset(); + } - const filter = Cell("", "filter"); + const filter = Cell("", "filter"); - const query = (): People => - people.filter(filter.current).sort("name", locale.read()); + const query = (): People => + people.filter(filter.current).sort("name", locale.read()); - function rows(): (Person & { id: string })[] { - return query().rows; - } + function rows(): (Person & { id: string })[] { + return query().rows; + } - function total(): string { - const filteredCount = rows().length; - const totalCount = table.rows.length; + function total(): string { + const filteredCount = rows().length; + const totalCount = table.rows.length; - if (filteredCount === totalCount) { - return `items: ${totalCount}`; - } else { - return `items: ${filteredCount} filtered / ${totalCount} total`; - } + if (filteredCount === totalCount) { + return `items: ${totalCount}`; + } else { + return `items: ${filteredCount} filtered / ${totalCount} total`; } - - return { - append, - filter, - total, - rows, - people, - table, - }; } - ); + + return { + append, + filter, + total, + rows, + people, + table, + }; + }); return ( <> diff --git a/demos/react-store/src/components/DateFormatter.tsx b/demos/react-store/src/components/DateFormatter.tsx index 28f0fb88..71ab0205 100644 --- a/demos/react-store/src/components/DateFormatter.tsx +++ b/demos/react-store/src/components/DateFormatter.tsx @@ -1,10 +1,10 @@ import { useSetup } from "@starbeam/react"; import { - type ResourceBlueprint, Cell, type Reactive, - Resource, readReactive, + Resource, + type ResourceBlueprint, } from "@starbeam/universal"; import { diff --git a/demos/react/src/components/formatter/DateFormatter-v3.tsx b/demos/react/src/components/formatter/DateFormatter-v3.tsx index c277dc03..02fb2ecb 100644 --- a/demos/react/src/components/formatter/DateFormatter-v3.tsx +++ b/demos/react/src/components/formatter/DateFormatter-v3.tsx @@ -1,10 +1,10 @@ import js from "@starbeam/collections"; import { useSetup } from "@starbeam/react"; import { - type Reactive, - type ResourceBlueprint, Cell, + type Reactive, Resource, + type ResourceBlueprint, } from "@starbeam/universal"; import { diff --git a/demos/react/src/components/formatter/DateFormatterFinal.tsx b/demos/react/src/components/formatter/DateFormatterFinal.tsx index 60280a2f..70d7faac 100644 --- a/demos/react/src/components/formatter/DateFormatterFinal.tsx +++ b/demos/react/src/components/formatter/DateFormatterFinal.tsx @@ -2,8 +2,8 @@ import js from "@starbeam/collections"; import { use, useCell, useReactive } from "@starbeam/react"; import { type Reactive, - type ResourceBlueprint, Resource, + type ResourceBlueprint, } from "@starbeam/universal"; import { diff --git a/packages/preact/preact-testing-utils/src/testing.ts b/packages/preact/preact-testing-utils/src/testing.ts index 5b659a81..487cc72c 100644 --- a/packages/preact/preact-testing-utils/src/testing.ts +++ b/packages/preact/preact-testing-utils/src/testing.ts @@ -7,10 +7,10 @@ import { type Attributes, type ComponentChildren, type ComponentType, - type VNode, createElement, Fragment, h, + type VNode, } from "preact"; import { act } from "preact/test-utils"; import { renderToString } from "preact-render-to-string"; @@ -95,7 +95,7 @@ class Expect { } check(args: T): void { - if (this.#expectations && this.#expectations.html) { + if (this.#expectations?.html) { const expected = this.#expectations.html(...args); const string = renderToString( diff --git a/packages/preact/preact-utils/src/internals/elements.ts b/packages/preact/preact-utils/src/internals/elements.ts index 7709e0ac..a37a6eba 100644 --- a/packages/preact/preact-utils/src/internals/elements.ts +++ b/packages/preact/preact-utils/src/internals/elements.ts @@ -1,5 +1,6 @@ import { DisplayStruct } from "../inspect.js"; import { type InternalPreactVNode, InternalVNode } from "./vnode.js"; + const INITIAL_ID = 0; const ELEMENTS = new WeakMap(); diff --git a/packages/preact/preact-utils/src/internals/vnode.ts b/packages/preact/preact-utils/src/internals/vnode.ts index a956c82f..ea556566 100644 --- a/packages/preact/preact-utils/src/internals/vnode.ts +++ b/packages/preact/preact-utils/src/internals/vnode.ts @@ -2,16 +2,16 @@ import { type ComponentChild, type ComponentChildren, type ComponentType, - type VNode, Fragment, + type VNode, } from "preact"; import { DisplayStruct } from "../inspect.js"; import type { InternalPreactElement, InternalSource } from "../interfaces.js"; import { isProbablyVNode } from "../internals.js"; import { - type InternalPreactComponent, InternalComponent, + type InternalPreactComponent, } from "./component.js"; const BUILTINS = new Set([Fragment]); @@ -21,12 +21,10 @@ const INITIAL_ID = 0; export class InternalVNode { #delete = { parent: (): void => { - delete this.#vnode[KEYS._parent]; }, depth: (): void => { - delete this.#vnode[KEYS._depth]; }, } as const; diff --git a/packages/preact/preact/src/resource.ts b/packages/preact/preact/src/resource.ts index 7a556112..d445eeb7 100644 --- a/packages/preact/preact/src/resource.ts +++ b/packages/preact/preact/src/resource.ts @@ -1,4 +1,3 @@ -import type { ReadValue } from "@starbeam/reactive"; import type { IntoResourceBlueprint } from "@starbeam/resource"; import * as resource from "@starbeam/resource"; import { service as createService } from "@starbeam/service"; @@ -7,14 +6,14 @@ import { useMemo } from "preact/hooks"; import { getCurrentComponent } from "./options.js"; -export function use(blueprint: IntoResourceBlueprint): T { +export function use(blueprint: IntoResourceBlueprint): T { return useMemo(() => { const owner = verified(getCurrentComponent(), isPresent); return resource.use(blueprint, { lifetime: owner }); }, []).current; } -export function service(blueprint: IntoResourceBlueprint): T { +export function service(blueprint: IntoResourceBlueprint): T { return useMemo(() => { return createService(blueprint); }, []).current; diff --git a/packages/preact/preact/tests/support/testing.ts b/packages/preact/preact/tests/support/testing.ts index 1d321194..182864e5 100644 --- a/packages/preact/preact/tests/support/testing.ts +++ b/packages/preact/preact/tests/support/testing.ts @@ -5,11 +5,11 @@ import { type ComponentChildren, type ComponentClass, type ComponentType, - type FunctionComponent, - type VNode, createElement, Fragment, + type FunctionComponent, h, + type VNode, } from "preact"; import { act } from "preact/test-utils"; import { renderToString } from "preact-render-to-string"; diff --git a/packages/react/react/src/debug/warnings.ts b/packages/react/react/src/debug/warnings.ts index 232e6233..80eefbf9 100644 --- a/packages/react/react/src/debug/warnings.ts +++ b/packages/react/react/src/debug/warnings.ts @@ -10,11 +10,11 @@ if (import.meta.env.DEV) { WARNED = true; const description = RUNTIME.debug?.getUserFacing(tag.description); - const fullName = description + const _fullName = description ? RUNTIME.debug?.describe(description) ?? "an unknown reactive value" : "an unknown reactive value"; - const pad = Math.max( + const _pad = Math.max( ...["Created: ", "Accessed: "].map((s) => s.length) ); diff --git a/packages/react/react/src/element.ts b/packages/react/react/src/element.ts index 82eab34b..a5fa2b54 100644 --- a/packages/react/react/src/element.ts +++ b/packages/react/react/src/element.ts @@ -301,7 +301,7 @@ export function internalUseResource( host.on.layout(create); const formula = Formula(() => { - return (resourceCell.current?.current as T | undefined) ?? initial; + return resourceCell.current?.current ?? initial; }); host.on.cleanup(PUBLIC_TIMELINE.on.change(formula, host.notify)); diff --git a/packages/react/react/src/use-component-instance.ts b/packages/react/react/src/use-component-instance.ts index 36af848c..7eb59e30 100644 --- a/packages/react/react/src/use-component-instance.ts +++ b/packages/react/react/src/use-component-instance.ts @@ -4,10 +4,10 @@ import { useState } from "react"; * This hook produces a unique instance representing the current React * component. If it's called multiple times inside a single React component, * it will return the same instance. - * + * * It returns the same instance even in strict mode when the component * is rendered multiple times. - * + * * It doesn't use other Starbeam hooks, since it is used to build those hooks. */ export function useComponentInstance(): object { @@ -19,7 +19,6 @@ export function useComponentInstance(): object { // We use `useState` to get a unique instance for each component, and then // we use `useState` to store the instance in a ref. const [instance] = useState(() => ({})); - const [, setInstance] = useState(instance); + const [, _setInstance] = useState(instance); return instance; - } diff --git a/packages/react/react/src/use-service.ts b/packages/react/react/src/use-service.ts index 2db43281..a30bd8f8 100644 --- a/packages/react/react/src/use-service.ts +++ b/packages/react/react/src/use-service.ts @@ -1,4 +1,3 @@ -import type { ReadValue } from "@starbeam/reactive"; import type { IntoResourceBlueprint } from "@starbeam/resource"; import { CONTEXT } from "@starbeam/runtime"; import { service } from "@starbeam/service"; @@ -6,7 +5,7 @@ import { service } from "@starbeam/service"; import { ReactApp, useStarbeamApp } from "./context-provider.js"; import { useReactive } from "./use-reactive.js"; -export function useService(blueprint: IntoResourceBlueprint): T { +export function useService(blueprint: IntoResourceBlueprint): T { CONTEXT.app = ReactApp.instance(useStarbeamApp({ feature: "useService()" })); const instance = service(blueprint); diff --git a/packages/react/test-utils/index.ts b/packages/react/test-utils/index.ts index 6c845228..7c7a2f4b 100644 --- a/packages/react/test-utils/index.ts +++ b/packages/react/test-utils/index.ts @@ -1,7 +1,7 @@ export { act } from "./src/act.js"; export { html, react } from "./src/dom.js"; export { - type SetupTestRoot as SetupTestRender, RenderState, + type SetupTestRoot as SetupTestRender, testReact, } from "./src/modes.js"; diff --git a/packages/react/test-utils/src/dom.ts b/packages/react/test-utils/src/dom.ts index 67468e4a..4359a277 100644 --- a/packages/react/test-utils/src/dom.ts +++ b/packages/react/test-utils/src/dom.ts @@ -1,13 +1,13 @@ // @vitest-environment jsdom import { + createElement, + Fragment, type FunctionComponent, + isValidElement, type ReactElement, type ReactHTML, type ReactNode, - createElement, - Fragment, - isValidElement, } from "react"; type ReactProxyFunction = ReactHTML[E]; diff --git a/packages/react/test-utils/src/modes.ts b/packages/react/test-utils/src/modes.ts index d14a6e5a..eb0633b7 100644 --- a/packages/react/test-utils/src/modes.ts +++ b/packages/react/test-utils/src/modes.ts @@ -224,17 +224,17 @@ export class SetupTestRoot { this: SetupTestRoot, T>, render: (state: RenderState, props?: void) => ReactElement, props?: void - ): Promise>; + ): RenderResult; render( render: (state: RenderState, props: Props) => ReactElement, props: Props - ): Promise>; - async render( + ): RenderResult; + render( this: SetupTestRoot, any>, render: (state: RenderState, props?: any) => ReactElement, // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types props?: any - ): Promise> { + ): RenderResult { const state = new RenderState(); let i = 0; @@ -272,7 +272,7 @@ export class SetupTestRoot { props as Props ); - return Promise.resolve(renderResult); + return renderResult as RenderResult; } expectHTML(expectHtml: (value: T, props: Props) => string): this { diff --git a/packages/universal/debug/src/description/debug/description.ts b/packages/universal/debug/src/description/debug/description.ts index 1da54d58..cdf474aa 100644 --- a/packages/universal/debug/src/description/debug/description.ts +++ b/packages/universal/debug/src/description/debug/description.ts @@ -2,9 +2,9 @@ import { getFirst, isObject } from "@starbeam/core-utils"; import type { Api, CallStack, + DescFn, Description as IDescription, DescriptionDetails, - DescFn, Nesting, ReactiveId, ReactiveType, diff --git a/packages/universal/debug/src/description/debug/index.ts b/packages/universal/debug/src/description/debug/index.ts index ac588f17..ce213cda 100644 --- a/packages/universal/debug/src/description/debug/index.ts +++ b/packages/universal/debug/src/description/debug/index.ts @@ -1,4 +1,5 @@ import type { DescFn } from "@starbeam/interfaces"; import { Desc as desc } from "./description.js"; + export default desc satisfies DescFn; diff --git a/packages/universal/debug/src/setup.ts b/packages/universal/debug/src/setup.ts index 036f4dac..c9509260 100644 --- a/packages/universal/debug/src/setup.ts +++ b/packages/universal/debug/src/setup.ts @@ -3,9 +3,7 @@ if ( typeof require === "function" ) { try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const buffer = await import("buffer"); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access globalThis.Buffer = buffer.Buffer; } catch { // ignore diff --git a/packages/universal/interfaces/index.ts b/packages/universal/interfaces/index.ts index 63066373..cac2b791 100644 --- a/packages/universal/interfaces/index.ts +++ b/packages/universal/interfaces/index.ts @@ -1,7 +1,6 @@ export type * from "./src/debug/call-stack.js"; -export type * from "./src/debug/description.js"; export type * from "./src/debug/debug-runtime.js"; - +export type * from "./src/debug/description.js"; export type { CellTag, DelegateTag, @@ -15,9 +14,9 @@ export type { SubscriptionTarget, Tag, Tagged, - TagSet, TaggedReactive, TagMethods, + TagSet, } from "./src/protocol.js"; export type { ActiveFrame, @@ -29,4 +28,4 @@ export type { UpdateOptions, } from "./src/runtime.js"; export type { Timestamp, TimestampStatics } from "./src/timestamp.js"; -export type { Expand, Unsubscribe, Diff } from "./src/utils.js"; +export type { Diff, Expand, Unsubscribe } from "./src/utils.js"; diff --git a/packages/universal/interfaces/src/debug/debug-runtime.ts b/packages/universal/interfaces/src/debug/debug-runtime.ts index 018218a9..c8de9643 100644 --- a/packages/universal/interfaces/src/debug/debug-runtime.ts +++ b/packages/universal/interfaces/src/debug/debug-runtime.ts @@ -1,6 +1,6 @@ import type { Tag, Tagged } from "../protocol.js"; import type { CallerStackFn, CallStack } from "./call-stack.js"; -import type { DescriptionDetails, DescFn } from "./description.js"; +import type { DescFn, DescriptionDetails } from "./description.js"; export interface DebugRuntime { getUserFacing: ( diff --git a/packages/universal/reactive/src/utils.ts b/packages/universal/reactive/src/utils.ts index 649db7e5..275d1a22 100644 --- a/packages/universal/reactive/src/utils.ts +++ b/packages/universal/reactive/src/utils.ts @@ -1,5 +1,5 @@ import type * as interfaces from "@starbeam/interfaces"; -import type { Description, Tag, TaggedReactive } from "@starbeam/interfaces"; +import type { Description } from "@starbeam/interfaces"; import { TAG } from "@starbeam/shared"; import { Static } from "./primitives/static.js"; diff --git a/packages/universal/reactive/tests/cell.spec.ts b/packages/universal/reactive/tests/cell.spec.ts index 0128b628..df370938 100644 --- a/packages/universal/reactive/tests/cell.spec.ts +++ b/packages/universal/reactive/tests/cell.spec.ts @@ -1,5 +1,5 @@ import { Cell } from "@starbeam/reactive"; -import { describe, test, expect } from "@starbeam-workspace/test-utils"; +import { describe, expect, test } from "@starbeam-workspace/test-utils"; describe("Cell", () => { test("its current property works like a normal property", () => { diff --git a/packages/universal/reactive/tests/tsconfig.json b/packages/universal/reactive/tests/tsconfig.json new file mode 100644 index 00000000..297b76aa --- /dev/null +++ b/packages/universal/reactive/tests/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../../.config/tsconfig/tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationDir": "../../../../dist/types", + "declarationMap": true, + "outDir": "../../../../dist/packages", + "types": ["../../../env"] + }, + "exclude": ["dist/**/*"] +} diff --git a/packages/universal/universal/index.ts b/packages/universal/universal/index.ts index 4db2109a..29b0711e 100644 --- a/packages/universal/universal/index.ts +++ b/packages/universal/universal/index.ts @@ -1,28 +1,27 @@ +export { DEBUG_RENDERER } from "./src/debug-renderer.js"; +export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; +export { Freshness } from "./src/reactive-core/higher-level/freshness.js"; +export { + type Variant, + type VariantEntry, + Variants, + type VariantType, +} from "./src/reactive-core/variants.js"; export type { Reactive } from "@starbeam/interfaces"; export { Cell, type Equality, - Static, - Formula as PolledFormula, CachedFormula as Formula, Marker, + Formula as PolledFormula, read as readReactive, + Static, } from "@starbeam/reactive"; +export { Wrap } from "@starbeam/reactive/src/primitives/delegate.js"; export { Resource, type ResourceBlueprint, type ResourceRun, use, } from "@starbeam/resource"; -export { DEBUG_RENDERER } from "./src/debug-renderer.js"; -export { FormulaList } from "./src/reactive-core/higher-level/formula-list.js"; -export { - type Variant, - type VariantEntry, - Variants, - type VariantType, -} from "./src/reactive-core/variants.js"; -export { Wrap } from "@starbeam/reactive/src/primitives/delegate.js"; -export { Freshness } from "./src/reactive-core/higher-level/freshness.js"; - export { LIFETIME, PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; diff --git a/packages/universal/verify/src/assertions/basic.ts b/packages/universal/verify/src/assertions/basic.ts index 7ec91664..b2ee9d2d 100644 --- a/packages/universal/verify/src/assertions/basic.ts +++ b/packages/universal/verify/src/assertions/basic.ts @@ -1,3 +1,5 @@ +import { isPresentArray } from "@starbeam/core-utils"; + import { expected, toKind } from "../verify.js"; import { format } from "./describe.js"; import type { FixedArray, ReadonlyFixedArray } from "./type-utils.js"; @@ -99,8 +101,6 @@ export function hasLength(length: L): HasLength { return expected.associate(has, expected.toHave(`${length} items`)); } -import { isPresentArray } from "@starbeam/core-utils"; - export const hasItems = isPresentArray; // export function hasItems( diff --git a/packages/x/devtool/src/log/cell.tsx b/packages/x/devtool/src/log/cell.tsx index d180a20f..ed6fc0af 100644 --- a/packages/x/devtool/src/log/cell.tsx +++ b/packages/x/devtool/src/log/cell.tsx @@ -1,3 +1,6 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import "preact"; /** @jsxRuntime automatic @jsxImportSource preact */ diff --git a/packages/x/devtool/src/log/describe.tsx b/packages/x/devtool/src/log/describe.tsx index fa8abdcd..f18460bb 100644 --- a/packages/x/devtool/src/log/describe.tsx +++ b/packages/x/devtool/src/log/describe.tsx @@ -1,3 +1,9 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/restrict-template-expressions */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import "preact"; import { isPresentArray, isSingleItemArray } from "@starbeam/core-utils"; diff --git a/packages/x/devtool/src/log/frame.tsx b/packages/x/devtool/src/log/frame.tsx index cfaccdb0..79a88f3d 100644 --- a/packages/x/devtool/src/log/frame.tsx +++ b/packages/x/devtool/src/log/frame.tsx @@ -1,12 +1,15 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ /** @jsxRuntime automatic @jsxImportSource preact */ +import { logTag } from "@starbeam/debug"; +import type { CellTag, Timestamp } from "@starbeam/interfaces"; import type { JSX } from "preact"; import { DescribeLeaf } from "./describe.js"; - import { LogLineFor } from "./ui.js"; -import type { CellTag, Timestamp } from "@starbeam/interfaces"; -import { logTag } from "@starbeam/debug"; type FIXME = any; type FrameConsumeOperation = FIXME; diff --git a/packages/x/devtool/src/log/log.tsx b/packages/x/devtool/src/log/log.tsx index 577abdd5..e334d44c 100644 --- a/packages/x/devtool/src/log/log.tsx +++ b/packages/x/devtool/src/log/log.tsx @@ -1,5 +1,12 @@ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import "preact"; +import type { Timestamp } from "@starbeam/interfaces"; /** @jsxRuntime automatic @jsxImportSource preact */ import type { JSX } from "preact"; import { useMemo, useState } from "preact/hooks"; @@ -10,7 +17,6 @@ import { FrameConsumeLine } from "./frame.js"; import type { UpdatePane } from "./pane.js"; import { Pane, UiPane } from "./pane.js"; import { LogLine } from "./ui.js"; -import type { Timestamp } from "@starbeam/interfaces"; type FIXME = any; type DevtoolsOptions = FIXME; diff --git a/packages/x/devtool/src/log/tabs.tsx b/packages/x/devtool/src/log/tabs.tsx index 409527b2..3d3aad00 100644 --- a/packages/x/devtool/src/log/tabs.tsx +++ b/packages/x/devtool/src/log/tabs.tsx @@ -1,9 +1,11 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ /** @jsxRuntime automatic @jsxImportSource preact */ import type { JSX } from "preact"; import css from "./css/pane.css?inline"; -import { type UpdatePane, Pane, UiPane } from "./pane.js"; +import { Pane, UiPane, type UpdatePane } from "./pane.js"; type FIXME = any; type DevtoolsOptions = FIXME; diff --git a/packages/x/devtool/src/log/ui.tsx b/packages/x/devtool/src/log/ui.tsx index 055ce89c..e259bec5 100644 --- a/packages/x/devtool/src/log/ui.tsx +++ b/packages/x/devtool/src/log/ui.tsx @@ -1,3 +1,6 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /** @jsxRuntime automatic @jsxImportSource preact */ import { Timestamp } from "@starbeam/runtime"; diff --git a/packages/x/store/index.ts b/packages/x/store/index.ts index 898c369e..289b9189 100644 --- a/packages/x/store/index.ts +++ b/packages/x/store/index.ts @@ -1,4 +1,4 @@ export { type Aggregator, Average, Sum } from "./src/aggregate.js"; export { Filter } from "./src/filter.js"; -export { type TableRows, Query } from "./src/flat.js"; +export { Query, type TableRows } from "./src/flat.js"; export { type RowTypeFor, Table } from "./src/table.js"; diff --git a/workspace/build/index.d.ts b/workspace/build/index.d.ts index 6916a5eb..b54a2495 100644 --- a/workspace/build/index.d.ts +++ b/workspace/build/index.d.ts @@ -1,7 +1,7 @@ export { + Package, type PackageInfo, type PackageJSON, type ViteConfig as ViteExport, - Package, } from "./src/config.js"; export { default as importMeta } from "./src/import-meta.js"; diff --git a/workspace/build/src/config.js b/workspace/build/src/config.js index 0d07c1bf..624ea74d 100644 --- a/workspace/build/src/config.js +++ b/workspace/build/src/config.js @@ -257,7 +257,7 @@ export class Package { static async viteConfig(meta) { const pkg = Package.at(meta); - if (pkg) return pkg.#viteConfig(); + if (pkg) return await pkg.#viteConfig(); throw Error( `No package found at ${ @@ -494,7 +494,7 @@ function mapExternal(inline) { * @param {import("./config.js").ViteConfig} config */ async function viteConfig(config) { - return config; + return Promise.resolve(config); } /** diff --git a/workspace/eslint/src/base.js b/workspace/eslint/src/base.js index cd2c6415..79487e9c 100644 --- a/workspace/eslint/src/base.js +++ b/workspace/eslint/src/base.js @@ -1,6 +1,5 @@ -// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unsafe-call +// eslint-disable-next-line unused-imports/no-unused-vars const { Linter, ESLint } = require("eslint"); -// eslint-disable-next-line @typescript-eslint/no-unsafe-call const Rules = require("./rules.js"); /** @type {ESLint.ConfigData} */ diff --git a/workspace/eslint/src/esm.js b/workspace/eslint/src/esm.js index d262ec0b..e5a665bb 100644 --- a/workspace/eslint/src/esm.js +++ b/workspace/eslint/src/esm.js @@ -1,6 +1,5 @@ -// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unsafe-call +// eslint-disable-next-line unused-imports/no-unused-vars const { Linter, ESLint } = require("eslint"); -// eslint-disable-next-line @typescript-eslint/no-unsafe-call const Rules = require("./rules.js"); /** @type {ESLint.ConfigData} */ diff --git a/workspace/package/index.ts b/workspace/package/index.ts index 58512d9e..1cbb59b8 100644 --- a/workspace/package/index.ts +++ b/workspace/package/index.ts @@ -1,9 +1,9 @@ export { Package } from "./src/package.js"; export { - type Test, - type Tests, queryPackages, + type Test, TestName, + type Tests, } from "./src/packages.js"; export type { FilterKey, FilterOperator } from "./src/query/filters.js"; export { Filter } from "./src/query/filters.js"; diff --git a/workspace/package/src/package.ts b/workspace/package/src/package.ts index 9e48dfd6..70c97c08 100644 --- a/workspace/package/src/package.ts +++ b/workspace/package/src/package.ts @@ -7,14 +7,13 @@ import { stringify, } from "@starbeam/core-utils"; import type { JsonValue } from "@starbeam-workspace/json"; -import type { Glob, RegularFile } from "@starbeam-workspace/paths"; -import type { Directory } from "@starbeam-workspace/paths"; -import { type Workspace, fragment } from "@starbeam-workspace/reporter"; +import type { Directory, Glob, RegularFile } from "@starbeam-workspace/paths"; +import { fragment, type Workspace } from "@starbeam-workspace/reporter"; import type { Dependencies } from "./dependencies.js"; import { createDependencies } from "./dependencies.js"; import { StarbeamJsx, Test, TestName } from "./packages"; -import { type PackageInfo, type Used, AllTests } from "./packages"; +import { AllTests, type PackageInfo, type Used } from "./packages"; import { RawPackage } from "./raw-package"; import { Starbeam } from "./starbeam"; import { TypeScriptConfig } from "./typescript.js"; diff --git a/workspace/package/src/packages.ts b/workspace/package/src/packages.ts index 0f00bd4c..f85458ec 100644 --- a/workspace/package/src/packages.ts +++ b/workspace/package/src/packages.ts @@ -1,5 +1,5 @@ import { isPresentArray } from "@starbeam/core-utils"; -import { type Path, Directory } from "@starbeam-workspace/paths"; +import { Directory, type Path } from "@starbeam-workspace/paths"; import type { Workspace } from "@starbeam-workspace/reporter"; import { DisplayStruct, Union } from "@starbeam-workspace/shared"; import sh from "shell-escape-tag"; diff --git a/workspace/package/src/query/filters.ts b/workspace/package/src/query/filters.ts index 782ed19d..4a6ac76c 100644 --- a/workspace/package/src/query/filters.ts +++ b/workspace/package/src/query/filters.ts @@ -4,12 +4,12 @@ import { isSingleItemArray, } from "@starbeam/core-utils"; import type { Reporter } from "@starbeam-workspace/reporter"; +import type { UnionClass } from "@starbeam-workspace/shared"; import util from "util"; import type { Package } from "../package"; import { StarbeamType } from "../unions.js"; import { ParseError } from "./query"; -import type { UnionClass } from "@starbeam-workspace/shared"; export class SingleFilter implements Filter { readonly type = "ok"; diff --git a/workspace/package/src/unions.ts b/workspace/package/src/unions.ts index 18bd316d..544d8d9d 100644 --- a/workspace/package/src/unions.ts +++ b/workspace/package/src/unions.ts @@ -1,7 +1,7 @@ import { stringify } from "@starbeam/core-utils"; import type { JsonObject, JsonValue } from "@starbeam-workspace/json"; -import type { RegularFile } from "@starbeam-workspace/paths"; -import { type Directory, Globs } from "@starbeam-workspace/paths"; +import type { Directory, RegularFile } from "@starbeam-workspace/paths"; +import { Globs } from "@starbeam-workspace/paths"; import { type IntoUnionInstance, Union } from "@starbeam-workspace/shared"; export class StarbeamType extends Union( diff --git a/workspace/reporter/index.ts b/workspace/reporter/index.ts index 1bdd8950..e60ad59e 100644 --- a/workspace/reporter/index.ts +++ b/workspace/reporter/index.ts @@ -13,8 +13,8 @@ export { Fragment, fragment } from "./src/log.js"; export { LoggerState } from "./src/logger.js"; export { type ChangeResult, - type ReporterOptions, Reporter, + type ReporterOptions, } from "./src/reporter.js"; export type { AnyStyleName, diff --git a/workspace/reporter/src/fancy-header.ts b/workspace/reporter/src/fancy-header.ts index 31cf7002..eb7139e2 100644 --- a/workspace/reporter/src/fancy-header.ts +++ b/workspace/reporter/src/fancy-header.ts @@ -1,8 +1,8 @@ import { type Printable, Style, StyleInstance } from "./log.js"; import { type StyleName, - type StylePartName, StylePart, + type StylePartName, STYLES, } from "./styles.js"; diff --git a/workspace/reporter/src/format.ts b/workspace/reporter/src/format.ts index bec9967d..e351efb2 100644 --- a/workspace/reporter/src/format.ts +++ b/workspace/reporter/src/format.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import wrap from "wrap-ansi"; import { SPACES_PER_TAB } from "./constants.js"; -import { type IntoFragment, Fragment, Style } from "./log.js"; +import { Fragment, type IntoFragment, Style } from "./log.js"; import type { InternalLogOptions, LeadingOption } from "./reporter.js"; const INCREMENT_LEADING = 1; diff --git a/workspace/reporter/src/log.ts b/workspace/reporter/src/log.ts index 3a05caea..29177490 100644 --- a/workspace/reporter/src/log.ts +++ b/workspace/reporter/src/log.ts @@ -8,14 +8,14 @@ import type { LoggerState } from "./logger.js"; import type { ReporterOptions } from "./reporter.js"; import { type AnyStyleName, - type IntoStylePart, - type StyleName, - type StylePartName, getStyle, hasPart, + type IntoStylePart, isAnyStyleName, STYLE, + type StyleName, StylePart, + type StylePartName, STYLES, } from "./styles.js"; diff --git a/workspace/reporter/src/logger.ts b/workspace/reporter/src/logger.ts index d0a49c26..524f671c 100644 --- a/workspace/reporter/src/logger.ts +++ b/workspace/reporter/src/logger.ts @@ -6,9 +6,9 @@ import { SPACES_PER_TAB } from "./constants.js"; import { wrapIndented, wrapLines } from "./format.js"; import { type DensityChoice, + Fragment, type FragmentImpl, type IntoFragment, - Fragment, } from "./log.js"; import type { LoggerEndWith, LogOptions, ReporterOptions } from "./reporter.js"; diff --git a/workspace/reporter/src/reporter.ts b/workspace/reporter/src/reporter.ts index e0166897..eb2dc37b 100644 --- a/workspace/reporter/src/reporter.ts +++ b/workspace/reporter/src/reporter.ts @@ -1,32 +1,28 @@ import { inspect } from "node:util"; import { stringify } from "@starbeam/core-utils"; -import type { Result } from "@starbeam-workspace/shared"; -import { - type IntoPresentArray, - FATAL_EXIT_CODE, - PresentArray, -} from "@starbeam-workspace/shared"; +import type { type IntoPresentArray, Result } from "@starbeam-workspace/shared"; +import { FATAL_EXIT_CODE, PresentArray } from "@starbeam-workspace/shared"; import chalk from "chalk"; -import { type GroupedCheckResults, CheckResults } from "./checks.js"; +import { CheckResults, type GroupedCheckResults } from "./checks.js"; import { SPACES_PER_TAB } from "./constants.js"; import type { Workspace } from "./interfaces.js"; import { - type IntoFallibleFragment, - type IntoFragment, - type IntoFragmentMap, Fragment, fragment, FragmentImpl, FragmentMap, + type IntoFallibleFragment, + type IntoFragment, + type IntoFragmentMap, isIntoFragment, LogResult, Style, } from "./log.js"; -import { type LoggerName, type LoggerState, Logger } from "./logger.js"; +import { Logger, type LoggerName, type LoggerState } from "./logger.js"; import { STYLES } from "./styles.js"; -import { type TableWithRows, Cell, LoggedTable } from "./table.js"; +import { Cell, LoggedTable, type TableWithRows } from "./table.js"; export interface ReporterOptions { readonly verbose: boolean; diff --git a/workspace/reporter/src/styles.ts b/workspace/reporter/src/styles.ts index c31ebba5..316d360e 100644 --- a/workspace/reporter/src/styles.ts +++ b/workspace/reporter/src/styles.ts @@ -1,7 +1,7 @@ import { type AsString, type Into, Union } from "@starbeam-workspace/shared"; import chalk from "chalk"; -import { type DetailedStyle, type StyleInstance, isDetailed } from "./log.js"; +import { type DetailedStyle, isDetailed, type StyleInstance } from "./log.js"; export const STYLE = Symbol("STYLE"); export type STYLE = typeof STYLE; diff --git a/workspace/reporter/src/table.ts b/workspace/reporter/src/table.ts index 82457ee3..07934ddc 100644 --- a/workspace/reporter/src/table.ts +++ b/workspace/reporter/src/table.ts @@ -3,9 +3,9 @@ import { DisplayStruct } from "@starbeam-workspace/shared"; import Table from "cli-table3"; import { - type IntoFragment, EMPTY_WIDTH, Fragment, + type IntoFragment, isIntoFragment, } from "./log.js"; import type { LoggerState } from "./logger.js"; diff --git a/workspace/scripts/src/ci.ts b/workspace/scripts/src/ci.ts index 14be25ad..5640231e 100644 --- a/workspace/scripts/src/ci.ts +++ b/workspace/scripts/src/ci.ts @@ -3,7 +3,7 @@ import { CheckDefinition } from "@starbeam-workspace/workspace"; import { QueryCommand } from "./support/commands/query-command"; import { StringOption } from "./support/commands/types"; -import scripts, { type Scripts, hydrateScript } from "./support/scripts.js"; +import scripts, { hydrateScript, type Scripts } from "./support/scripts.js"; export const CiCommand = QueryCommand("ci") .flag( diff --git a/workspace/scripts/src/clean.ts b/workspace/scripts/src/clean.ts index e0f71696..60641548 100644 --- a/workspace/scripts/src/clean.ts +++ b/workspace/scripts/src/clean.ts @@ -3,8 +3,7 @@ import { relative } from "node:path"; import { isPresentArray } from "@starbeam/core-utils"; import { Package } from "@starbeam-workspace/package"; -import type { Reporter } from "@starbeam-workspace/reporter"; -import type { Workspace } from "@starbeam-workspace/reporter"; +import type { Reporter, Workspace } from "@starbeam-workspace/reporter"; import { Fragment } from "@starbeam-workspace/reporter"; import { fatal } from "@starbeam-workspace/shared"; import glob from "fast-glob"; diff --git a/workspace/scripts/src/support/commands/build-command.ts b/workspace/scripts/src/support/commands/build-command.ts index d2211770..2bca86d2 100644 --- a/workspace/scripts/src/support/commands/build-command.ts +++ b/workspace/scripts/src/support/commands/build-command.ts @@ -7,11 +7,11 @@ import { type CamelizedOptions, type CheckOption, type CommandOptions, - type LongFlag, - type ShortFlag, dasherize, + type LongFlag, normalize, normalizeFlag, + type ShortFlag, } from "./options"; import type { CommandValue, Value } from "./types"; @@ -81,7 +81,7 @@ export abstract class BuildCommand { name: string, description: string, value: Value - // eslint-disable-next-line @typescript-eslint/prefer-return-this-type + // eslint-disable-next-line @typescript-eslint/prefer-return-this-type ): BuildCommand { const arg = dasherize(name); diff --git a/workspace/scripts/src/support/commands/dev-command.ts b/workspace/scripts/src/support/commands/dev-command.ts index 52d53a48..5767016e 100644 --- a/workspace/scripts/src/support/commands/dev-command.ts +++ b/workspace/scripts/src/support/commands/dev-command.ts @@ -4,6 +4,7 @@ import { program as CommanderProgram } from "commander"; import { BuildCommand } from "./build-command"; import type { Arg, + BasicOptions, CamelizedOptions, CheckOption, CommandOptions, @@ -11,7 +12,6 @@ import type { ShortCommandOptions, ShortFlag, } from "./options"; -import type { BasicOptions } from "./options"; import { applyBasicOptions } from "./options"; import { createWorkspace } from "./query-command.js"; import type { CommandValue, Value } from "./types"; @@ -65,7 +65,7 @@ export class BuildDevCommand< ) => void | Promise ): (options: { root: string }) => Command { return ({ root }) => - this.command.action((...args) => { + this.command.action(async (...args) => { const { options } = this.extractOptions(args); return action( ...(this.parseOptions(args, { diff --git a/workspace/scripts/src/support/commands/query-command.ts b/workspace/scripts/src/support/commands/query-command.ts index 396460c9..1454b19e 100644 --- a/workspace/scripts/src/support/commands/query-command.ts +++ b/workspace/scripts/src/support/commands/query-command.ts @@ -1,13 +1,19 @@ -import type { Package } from "@starbeam-workspace/package"; -import { type ParseError, FILTER_KEYS } from "@starbeam-workspace/package"; -import { queryPackages } from "@starbeam-workspace/package"; -import { Filter, formatScope, parse, Query } from "@starbeam-workspace/package"; +import type { Package, type ParseError } from "@starbeam-workspace/package"; import { - type Workspace as IWorkspace, + Filter, + FILTER_KEYS, + formatScope, + parse, + Query, + queryPackages, +} from "@starbeam-workspace/package"; +import { + format, Fragment, + type ReporterOptions, + type Workspace as IWorkspace, wrapIndented, } from "@starbeam-workspace/reporter"; -import { type ReporterOptions, format } from "@starbeam-workspace/reporter"; import { Workspace } from "@starbeam-workspace/workspace"; import chalk from "chalk"; import type { Command } from "commander"; diff --git a/workspace/scripts/src/support/scripts.ts b/workspace/scripts/src/support/scripts.ts index e794d44d..feaabdc8 100644 --- a/workspace/scripts/src/support/scripts.ts +++ b/workspace/scripts/src/support/scripts.ts @@ -1,6 +1,5 @@ import type { Package } from "@starbeam-workspace/package"; -import type { Directory } from "@starbeam-workspace/paths"; -import type { Path } from "@starbeam-workspace/paths"; +import type { Directory, Path } from "@starbeam-workspace/paths"; import type { Workspace } from "@starbeam-workspace/reporter"; import scripts from "../scripts.json"; diff --git a/workspace/scripts/src/support/template/update-package-json.ts b/workspace/scripts/src/support/template/update-package-json.ts index 2bb2662a..fbf140d4 100644 --- a/workspace/scripts/src/support/template/update-package-json.ts +++ b/workspace/scripts/src/support/template/update-package-json.ts @@ -1,8 +1,8 @@ import { isSingleItemArray } from "@starbeam/core-utils"; import { + isObject, type JsonObject, type JsonValue, - isObject, } from "@starbeam-workspace/json"; import type { Package } from "@starbeam-workspace/package"; import { Fragment, fragment } from "@starbeam-workspace/reporter"; diff --git a/workspace/scripts/src/support/template/update-package.ts b/workspace/scripts/src/support/template/update-package.ts index f631b730..1771b2b0 100644 --- a/workspace/scripts/src/support/template/update-package.ts +++ b/workspace/scripts/src/support/template/update-package.ts @@ -8,8 +8,7 @@ import { JsonTemplate, Template } from "@starbeam-workspace/package"; import type { Directory, Path, Paths } from "@starbeam-workspace/paths"; import type { ChangeResult } from "@starbeam-workspace/reporter"; import { Fragment, fragment } from "@starbeam-workspace/reporter"; -import type { Into } from "@starbeam-workspace/shared"; -import type { AsString } from "@starbeam-workspace/shared"; +import type { AsString, Into } from "@starbeam-workspace/shared"; import type { Workspace } from "@starbeam-workspace/workspace"; import sh from "shell-escape-tag"; diff --git a/workspace/scripts/src/test.ts b/workspace/scripts/src/test.ts index 58c201bb..21efd906 100644 --- a/workspace/scripts/src/test.ts +++ b/workspace/scripts/src/test.ts @@ -3,9 +3,8 @@ import { isSingleItemArray, stringify, } from "@starbeam/core-utils"; -import { type Test, Package, TestName } from "@starbeam-workspace/package"; -import { Fragment } from "@starbeam-workspace/reporter"; -import { FancyHeader } from "@starbeam-workspace/reporter"; +import { Package, type Test, TestName } from "@starbeam-workspace/package"; +import { FancyHeader, Fragment } from "@starbeam-workspace/reporter"; import { fatal } from "@starbeam-workspace/shared"; import { CheckDefinition } from "@starbeam-workspace/workspace"; import shell from "shelljs"; diff --git a/workspace/shared/index.ts b/workspace/shared/index.ts index 96741025..ecb84453 100644 --- a/workspace/shared/index.ts +++ b/workspace/shared/index.ts @@ -11,7 +11,7 @@ export type { IntoUnionInstance, OkRecord, OkResult, - UnionInstance, UnionClass, + UnionInstance, } from "./src/type-magic.js"; export { PresentArray, Result, Union } from "./src/type-magic.js"; diff --git a/workspace/test-utils/index.ts b/workspace/test-utils/index.ts index 8ef6abdc..6e1bbeb9 100644 --- a/workspace/test-utils/index.ts +++ b/workspace/test-utils/index.ts @@ -1,7 +1,7 @@ export { - type TestResourceImpl, resources, TestResource, + type TestResourceImpl, } from "./src/test-resource.js"; export { assert, UNINITIALIZED } from "./src/utils.js"; export { diff --git a/workspace/test-utils/src/vitest.ts b/workspace/test-utils/src/vitest.ts index 0aa933d6..37d126fe 100644 --- a/workspace/test-utils/src/vitest.ts +++ b/workspace/test-utils/src/vitest.ts @@ -9,6 +9,7 @@ import { test, vi, } from "vitest"; + export { afterEach, beforeAll, diff --git a/workspace/workspace/src/checks.ts b/workspace/workspace/src/checks.ts index 6230b855..360b3717 100644 --- a/workspace/workspace/src/checks.ts +++ b/workspace/workspace/src/checks.ts @@ -1,5 +1,5 @@ import type { Directory } from "@starbeam-workspace/paths"; -import { type CheckResult, Check } from "@starbeam-workspace/reporter"; +import { Check, type CheckResult } from "@starbeam-workspace/reporter"; import { CheckResults } from "@starbeam-workspace/reporter"; import type { CommandOutputType, Workspace } from "./workspace.js"; diff --git a/workspace/workspace/src/workspace.ts b/workspace/workspace/src/workspace.ts index 95253597..d2df926c 100644 --- a/workspace/workspace/src/workspace.ts +++ b/workspace/workspace/src/workspace.ts @@ -1,21 +1,27 @@ import { stringify } from "@starbeam/core-utils"; -import type { Directory, Glob, Path } from "@starbeam-workspace/paths"; -import { type GlobOptions, Paths } from "@starbeam-workspace/paths"; +import type { + Directory, + Glob, + GlobOptions, + Path, +} from "@starbeam-workspace/paths"; +import { Paths } from "@starbeam-workspace/paths"; import type { CheckResults, + IntoFragment, + ReporterOptions, Workspace as IWorkspace, } from "@starbeam-workspace/reporter"; import { - type IntoFragment, + CommandStream, Fragment, fragment, GroupedCheckResults, + Reporter, } from "@starbeam-workspace/reporter"; -import { CommandStream } from "@starbeam-workspace/reporter"; -import { type ReporterOptions, Reporter } from "@starbeam-workspace/reporter"; import { - type ExecSyncOptionsWithStringEncoding, execSync, + type ExecSyncOptionsWithStringEncoding, } from "child_process"; import { Checks } from "./checks.js"; From e77a419a22a9ceaa25ceb9216333f654d55b34be Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 15:03:51 -0700 Subject: [PATCH 41/46] Re-fix ci:types --- workspace/reporter/src/reporter.ts | 2 +- workspace/scripts/src/support/commands/query-command.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace/reporter/src/reporter.ts b/workspace/reporter/src/reporter.ts index eb2dc37b..2084407d 100644 --- a/workspace/reporter/src/reporter.ts +++ b/workspace/reporter/src/reporter.ts @@ -1,7 +1,7 @@ import { inspect } from "node:util"; import { stringify } from "@starbeam/core-utils"; -import type { type IntoPresentArray, Result } from "@starbeam-workspace/shared"; +import type { IntoPresentArray, Result } from "@starbeam-workspace/shared"; import { FATAL_EXIT_CODE, PresentArray } from "@starbeam-workspace/shared"; import chalk from "chalk"; diff --git a/workspace/scripts/src/support/commands/query-command.ts b/workspace/scripts/src/support/commands/query-command.ts index 1454b19e..7888bc7f 100644 --- a/workspace/scripts/src/support/commands/query-command.ts +++ b/workspace/scripts/src/support/commands/query-command.ts @@ -1,4 +1,4 @@ -import type { Package, type ParseError } from "@starbeam-workspace/package"; +import type { Package, ParseError } from "@starbeam-workspace/package"; import { Filter, FILTER_KEYS, From fa0a112dcd6c8e4b6cd254aa60c792a6ea353a4a Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 15:42:11 -0700 Subject: [PATCH 42/46] Fix FIXME: renderer unsubscriptions Also remove a bunch of errant console.logs --- .../react/react/tests/use-starbeam.spec.ts | 9 +- packages/universal/debug/src/tag.ts | 2 +- packages/universal/resource/src/resource.ts | 4 - .../resource/tests/resource-list.spec.ts | 1 - .../runtime/src/timeline/subscriptions.ts | 37 +++-- .../runtime/tests/subscribing.spec.ts | 135 +++++++++++++++++- .../universal/tests/variants.spec.ts | 2 +- workspace/reporter/src/log.ts | 2 +- 8 files changed, 163 insertions(+), 29 deletions(-) diff --git a/packages/react/react/tests/use-starbeam.spec.ts b/packages/react/react/tests/use-starbeam.spec.ts index 7b41d558..34d790d6 100644 --- a/packages/react/react/tests/use-starbeam.spec.ts +++ b/packages/react/react/tests/use-starbeam.spec.ts @@ -41,7 +41,6 @@ describe("useStarbeam", () => { const resource = use(testResource); return Formula(() => { - console.log({ resource, current: resource.current }); state.value(resource.current); return html.span(resource.current?.count ?? "uninitialized"); }); @@ -56,19 +55,15 @@ describe("useStarbeam", () => { }); testReact("using a service", async (root) => { - const result = await root + const result = root .expectHTML((value) => `${value?.count ?? "uninitialized"}`) - .render((state) => { - console.log("inside Starbeam frame"); - return createElement(Starbeam, null, react.render(App, { state })); - }); + .render((state) => createElement(Starbeam, null, react.render(App, { state }))); function App({ state }: { state: RenderState }) { return useStarbeam(({ service }) => { const resource = service(testResource); return Formula(() => { - console.log({ resource: resource.current?.count }); state.value(resource.current); return html.span(resource.current?.count ?? "uninitialized"); }); diff --git a/packages/universal/debug/src/tag.ts b/packages/universal/debug/src/tag.ts index fd682baa..425b7211 100644 --- a/packages/universal/debug/src/tag.ts +++ b/packages/universal/debug/src/tag.ts @@ -39,7 +39,7 @@ export const logTag = ( describe(tag.description, { id: options.id }), `(updated at ${tag.lastUpdated.toString({ format: "timestamp" })})` ); - console.log(debug); + console.info(debug); console.groupEnd(); }; diff --git a/packages/universal/resource/src/resource.ts b/packages/universal/resource/src/resource.ts index 3650442c..0837f367 100644 --- a/packages/universal/resource/src/resource.ts +++ b/packages/universal/resource/src/resource.ts @@ -146,10 +146,6 @@ export class ResourceBlueprintImpl { const metadata = options.metadata ?? (blueprint.#metadata as M); const description = options.description ?? blueprint.#description; - if (lifetime === undefined) { - console.trace({ blueprint, options, lifetime }); - } - return evaluateResourceConstructor( { Constructor, diff --git a/packages/universal/resource/tests/resource-list.spec.ts b/packages/universal/resource/tests/resource-list.spec.ts index 211b5340..b7d903be 100644 --- a/packages/universal/resource/tests/resource-list.spec.ts +++ b/packages/universal/resource/tests/resource-list.spec.ts @@ -115,7 +115,6 @@ describe("ResourceList", () => { subscription.connect(); on.cleanup(() => { - console.trace({ disconnecting: item.id }); subscription.disconnect(); }); diff --git a/packages/universal/runtime/src/timeline/subscriptions.ts b/packages/universal/runtime/src/timeline/subscriptions.ts index a41191e5..2ea6146b 100644 --- a/packages/universal/runtime/src/timeline/subscriptions.ts +++ b/packages/universal/runtime/src/timeline/subscriptions.ts @@ -25,10 +25,15 @@ export class Subscriptions { readonly #queuedSubscriptions = new WeakSetMap(); register(tag: Tag, ready: NotifyReady): Unsubscribe { - const unsubscribes = getTargets(tag).map((t) => this.#subscribe(t, ready)); + const targets = getTargets(tag); + targets.forEach((t) => { + this.#subscribe(t, ready); + }); return () => { - for (const unsubscribe of unsubscribes) unsubscribe(); + for (const target of targets) { + this.#unsubscribe(target, ready); + } }; } @@ -58,14 +63,18 @@ export class Subscriptions { } } - #subscribe(target: SubscriptionTarget, ready: NotifyReady) { + #unsubscribe(target: SubscriptionTarget, ready: NotifyReady) { if (target.type === "formula" && !target.initialized) { - const set = this.#queuedSubscriptions.add(target, ready); + this.#queuedSubscriptions.delete(target, ready); + } else { + const subscription = this.#tagSubscriptions.get(target); + subscription.unsubscribe(ready); + } + } - // FIXME: Support removal after upgrade - return () => { - set.delete(ready); - }; + #subscribe(target: SubscriptionTarget, ready: NotifyReady): void { + if (target.type === "formula" && !target.initialized) { + this.#queuedSubscriptions.add(target, ready); } else { const subscription = this.#tagSubscriptions.get(target); @@ -74,13 +83,15 @@ export class Subscriptions { this.#cellSubscriptions.add(cell, subscription); } - return subscription.subscribe(ready); + subscription.subscribe(ready); + return; } } } interface Subscription { - readonly subscribe: (ready: NotifyReady) => Unsubscribe; + readonly subscribe: (ready: NotifyReady) => void; + readonly unsubscribe: (ready: NotifyReady) => void; readonly notify: (cell: CellTag) => void; readonly update: (formula: FormulaTag) => Diff; } @@ -94,6 +105,10 @@ function Subscription(tag: Tag): Subscription { return () => readySet.delete(ready); } + function unsubscribe(ready: NotifyReady): void { + readySet.delete(ready); + } + function notify(cell: CellTag) { for (const ready of readySet) ready(cell); } @@ -106,7 +121,7 @@ function Subscription(tag: Tag): Subscription { return diff(prev, next); } - return { subscribe, notify, update }; + return { subscribe, unsubscribe, notify, update }; } const EMPTY_SET = new Set(); diff --git a/packages/universal/runtime/tests/subscribing.spec.ts b/packages/universal/runtime/tests/subscribing.spec.ts index f9483243..eba4024d 100644 --- a/packages/universal/runtime/tests/subscribing.spec.ts +++ b/packages/universal/runtime/tests/subscribing.spec.ts @@ -1,5 +1,4 @@ import { isPresentArray } from "@starbeam/core-utils"; -import { logTag } from "@starbeam/debug"; import type { ReactiveValue } from "@starbeam/interfaces"; import { CachedFormula, Cell, RUNTIME } from "@starbeam/reactive"; import { PUBLIC_TIMELINE, TAG } from "@starbeam/runtime"; @@ -147,9 +146,7 @@ describe("Tagged", () => { expect(delegate.read()).toBe(3); - logTag(delegate[TAG]); satisfying(numbers.current, isPresentArray)[0].current++; - logTag(delegate[TAG]); expect(stale).toBe(true); stale = false; @@ -167,6 +164,138 @@ describe("Tagged", () => { expect(delegate.read()).toBe(8); }); + + describe("unsubscribing", () => { + test("unsubscribing from a cell", () => { + const cell = Cell(0); + let stale = false; + + const unsubscribe = PUBLIC_TIMELINE.on.change(cell, () => { + stale = true; + }); + + expect(stale).toBe(false); + + cell.current++; + + expect(stale).toBe(true); + stale = false; + + unsubscribe(); + + cell.current++; + + expect(stale).toBe(false); + }); + + test("unsubscribing from a formula", () => { + const { sum, numbers } = Sum(); + let stale = false; + + expect(sum.read()).toBe(0); + const unsubscribe = PUBLIC_TIMELINE.on.change(sum, () => { + stale = true; + }); + + expect(stale).toBe(false); + + numbers.current = [...numbers.current, Cell(1), Cell(2)]; + + expect(stale).toBe(true); + stale = false; + + unsubscribe(); + + numbers.current = [...numbers.current, Cell(3)]; + + expect(stale).toBe(false); + }); + + test("unsubscribing from a delegate", () => { + const cell = Cell(0); + + const delegate: ReactiveValue = { + read: () => cell.current, + [TAG]: createDelegateTag(RUNTIME.Desc?.("delegate"), [getTag(cell)]), + }; + + let stale = false; + + const unsubscribe = PUBLIC_TIMELINE.on.change(delegate, () => { + stale = true; + }); + + expect(stale).toBe(false); + + cell.current++; + + expect(stale).toBe(true); + stale = false; + + unsubscribe(); + + cell.current++; + + expect(stale).toBe(false); + }); + + test("unsubscribe from a subcription to an uninitialized formula before it was initialized", () => { + const { sum, numbers } = Sum(); + let stale = false; + + const unsubscribe = PUBLIC_TIMELINE.on.change(sum, () => { + stale = true; + }); + + expect(stale).toBe(false); + + // unsubscribing before the formula is initialized + unsubscribe(); + + expect(sum.read()).toBe(0); + expect(stale).toBe(false); + + numbers.current = [...numbers.current, Cell(1), Cell(2)]; + expect(sum.read()).toBe(3); + expect(stale).toBe(false); + }); + + test("unsubscribing from a subscription to an uninitialized formula after it was initialized", () => { + const { sum, numbers } = Sum(); + let stale = false; + + const unsubscribe = PUBLIC_TIMELINE.on.change(sum, () => { + stale = true; + }); + + expect(stale).toBe(false); + + numbers.current = [...numbers.current, Cell(1), Cell(2)]; + + // the subscription is queued. It will be called when the formula is + // initialized, but not before. + expect(stale).toBe(false); + + // the formula is initialized + expect(sum.read()).toBe(3); + + // the subscription is still not called, because the subscriptions are + // only called when the value they represent is updated. + expect(stale).toBe(false); + + numbers.current = [...numbers.current, Cell(3)]; + + // the subscription is called, because the formula is updated + expect(stale).toBe(true); + stale = false; + + unsubscribe(); + + numbers.current = [...numbers.current, Cell(4)]; + + expect(stale).toBe(false); + }); + }); }); function Sum(): { diff --git a/packages/universal/universal/tests/variants.spec.ts b/packages/universal/universal/tests/variants.spec.ts index 2847bd40..0cf6488a 100644 --- a/packages/universal/universal/tests/variants.spec.ts +++ b/packages/universal/universal/tests/variants.spec.ts @@ -220,7 +220,7 @@ function Stability(reactive: Tagged): { RUNTIME.debug?.describeTagged(reactive) ?? "{unknown reactive value}", "invalidated by" ); - console.log(internals.description); + console.info(internals.description); console.groupEnd(); } changed = true; diff --git a/workspace/reporter/src/log.ts b/workspace/reporter/src/log.ts index 29177490..46494d8c 100644 --- a/workspace/reporter/src/log.ts +++ b/workspace/reporter/src/log.ts @@ -59,7 +59,7 @@ export const Style = { } as const; export function log(message: string, style: Style = Style.default): void { - console.log(Fragment(style, message)); + console.info(Fragment(style, message)); } log.newline = () => { From f647b5fd24e5f657b2b3131ef57fd6e19c8726df Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 15:57:25 -0700 Subject: [PATCH 43/46] Re-fix ci:lint --- packages/react/react/tests/use-starbeam.spec.ts | 6 ++++-- .../tests/use-lifecycle.spec.ts | 14 +++++++------- .../universal/interfaces/src/debug/description.ts | 2 -- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/react/react/tests/use-starbeam.spec.ts b/packages/react/react/tests/use-starbeam.spec.ts index 34d790d6..88cf5e22 100644 --- a/packages/react/react/tests/use-starbeam.spec.ts +++ b/packages/react/react/tests/use-starbeam.spec.ts @@ -34,7 +34,7 @@ describe("useStarbeam", () => { } testReact("using a resource", async (root) => { - const result = await root + const result = root .expectHTML((value) => `${value?.count ?? "uninitialized"}`) .render((state) => { return useStarbeam(({ use }) => { @@ -57,7 +57,9 @@ describe("useStarbeam", () => { testReact("using a service", async (root) => { const result = root .expectHTML((value) => `${value?.count ?? "uninitialized"}`) - .render((state) => createElement(Starbeam, null, react.render(App, { state }))); + .render((state) => + createElement(Starbeam, null, react.render(App, { state })) + ); function App({ state }: { state: RenderState }) { return useStarbeam(({ service }) => { diff --git a/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts b/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts index af4d871b..ab094d54 100644 --- a/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/use-lifecycle.spec.ts @@ -10,7 +10,7 @@ testReact( async (root, mode) => { TestResource.resetId(); - const result = await root + const result = root .expectStable() .expectHTML(({ lastState, lastCount }) => { return `

    ${lastState}

    ${lastCount}

    `; @@ -87,8 +87,8 @@ testReact( } ); -testReact("most basic useLifecycle", async (root) => { - await root +testReact("most basic useLifecycle", (root) => { + root .expectStable() .expectHTML(({ count }) => `
    ${count}
    `) .render((setup) => { @@ -107,7 +107,7 @@ testReact("most basic useLifecycle", async (root) => { }); testReact("useLifecycle with update", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML(({ count }) => `
    ${count}
    `) .render((setup) => { @@ -147,7 +147,7 @@ testReact("useLifecycle with update", async (root) => { testReact( "useLifecycle with cleanup", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML(({ count }) => `
    ${count}
    `) .render((setup) => { @@ -196,7 +196,7 @@ testReact( testReact( "useLifecycle with cleanup and prev", async (root, mode) => { - const result = await root + const result = root .expectStable() .expectHTML(({ count }) => `
    ${count}
    `) .render((setup) => { @@ -259,7 +259,7 @@ testReact( testReact( "useLifecycle with invalidation", async (root, mode) => { - const result = await root + const result = root .expectStable() .expectHTML( ({ count }) => diff --git a/packages/universal/interfaces/src/debug/description.ts b/packages/universal/interfaces/src/debug/description.ts index d52584da..78220d03 100644 --- a/packages/universal/interfaces/src/debug/description.ts +++ b/packages/universal/interfaces/src/debug/description.ts @@ -12,8 +12,6 @@ export type ReactiveType = export type DescFn = ( type: ReactiveType, specified?: string | Description | undefined, - // FIXME: speculative inference strategy: if you have a call stack, use the - // action from the caller frame as the default API name api?: Api | string | undefined ) => Description | undefined; From 048d5b86fb3d3a57fd93dbb6da3916abc86fb0ab Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 16:03:19 -0700 Subject: [PATCH 44/46] More ci:lint fixes --- demos/react-jsnation/tests/app.spec.tsx | 8 ++++---- packages/react/react/tests/use-reactive.spec.ts | 10 +++++----- packages/react/react/tests/use-resource.spec.ts | 10 +++++----- packages/react/react/tests/use-service.spec.ts | 2 +- packages/react/react/tests/use-setup.spec.ts | 8 ++++---- packages/react/react/tests/use-starbeam-app.spec.ts | 2 +- .../use-strict-lifecycle/tests/is-rendering.spec.ts | 2 +- .../use-strict-lifecycle/tests/updating-ref.spec.ts | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/demos/react-jsnation/tests/app.spec.tsx b/demos/react-jsnation/tests/app.spec.tsx index 3d8c25bb..82e7a2d2 100644 --- a/demos/react-jsnation/tests/app.spec.tsx +++ b/demos/react-jsnation/tests/app.spec.tsx @@ -5,8 +5,8 @@ import { describe, expect } from "@starbeam-workspace/test-utils"; import { ErrorBoundary } from "react-error-boundary"; describe("react-jsnation", () => { - testReact("App loads DataTable", async (root) => { - const result = await root.render((state) => { + testReact("App loads DataTable", (root) => { + const result = root.render((state) => { state.value(undefined); return (

    Error

    }> @@ -22,8 +22,8 @@ describe("react-jsnation", () => { expect(result.findByText("Create a new user").innerHTML).toBeDefined(); }); - testReact("App loads locale selector", async (root) => { - const result = await root.render((state) => { + testReact("App loads locale selector", (root) => { + const result = root.render((state) => { state.value(undefined); return (

    Error

    }> diff --git a/packages/react/react/tests/use-reactive.spec.ts b/packages/react/react/tests/use-reactive.spec.ts index 90daeed7..0179ce2b 100644 --- a/packages/react/react/tests/use-reactive.spec.ts +++ b/packages/react/react/tests/use-reactive.spec.ts @@ -15,7 +15,7 @@ let nextId = INITIAL_ID; describe("useReactive", () => { testReact("useReactiveSetup with useReactive", async (root) => { - const result = await root + const result = root .expectHTML((value) => `

    ${value}

    `) .render((state) => { const { cell, increment } = useSetup(() => { @@ -49,7 +49,7 @@ describe("useReactive", () => { "useSetup with Formula + useReactive", async (test) => { let testId = 0; - const result = await test + const result = test .expectHTML(({ counter }) => `

    ${counter}

    `) .expectStable() .render((state) => { @@ -78,7 +78,7 @@ describe("useReactive", () => { "useSetup with Formula + useReactive", async (root) => { nextId = INITIAL_ID; - const result = await root + const result = root .expectHTML(({ counter }) => `

    ${counter}

    `) .expectStable() .render((state) => { @@ -118,7 +118,7 @@ describe("useReactive", () => { testReact( "useReactive", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML( (count) => @@ -183,7 +183,7 @@ describe("useReactive", () => { testReact( "useReactiveSetup", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML( (count) => diff --git a/packages/react/react/tests/use-resource.spec.ts b/packages/react/react/tests/use-resource.spec.ts index bc3012ea..a96c5797 100644 --- a/packages/react/react/tests/use-resource.spec.ts +++ b/packages/react/react/tests/use-resource.spec.ts @@ -16,7 +16,7 @@ describe("useResource", () => { testReact<{ name: string }, string | null | undefined>( "using useProp", async (root) => { - const result = await root + const result = root .expectHTML((message) => `${message ?? "loading"}`) .render( (state, props) => { @@ -77,7 +77,7 @@ describe("useResource", () => { testReact<{ name: string }, string | null | undefined>( "using a dependency array", async (root) => { - const result = await root + const result = root .expectHTML((message) => `${message ?? "loading"}`) .render( (state, { name }) => { @@ -138,7 +138,7 @@ describe("useResource", () => { testReact<{ name: string }, string | null | undefined>( "the resource is created when the component is mounted, and effects run", async (root) => { - const result = await root + const result = root .expectHTML((message) => `${message ?? "loading"}`) .render( (state, { name }) => { @@ -210,7 +210,7 @@ describe("use", () => { >("using use() with dependencies", async (root, mode) => { ID = 0; - const result = await root + const result = root .expectHTML((state) => state?.channel?.message ? `${state?.channel.message}` @@ -291,7 +291,7 @@ describe("use", () => { >("using resource() from useSetup()", async (root, mode) => { ID = 0; - const result = await root + const result = root .expectHTML((state) => state?.channel?.message ? `${state?.channel.message}` diff --git a/packages/react/react/tests/use-service.spec.ts b/packages/react/react/tests/use-service.spec.ts index 4ff83424..4028367a 100644 --- a/packages/react/react/tests/use-service.spec.ts +++ b/packages/react/react/tests/use-service.spec.ts @@ -15,7 +15,7 @@ describe("services", () => { beforeEach(AUTH_CHANNELS.reset); testReact<{ name: string }, Auth | null>("useService", async (root) => { - const result = await root + const result = root .expectHTML((auth) => auth ? `${auth.username}` diff --git a/packages/react/react/tests/use-setup.spec.ts b/packages/react/react/tests/use-setup.spec.ts index 5f788e92..db77b15f 100644 --- a/packages/react/react/tests/use-setup.spec.ts +++ b/packages/react/react/tests/use-setup.spec.ts @@ -36,7 +36,7 @@ interface TestProps { describe("useSetup", () => { testReact("returning a render function", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML( (value) => @@ -87,7 +87,7 @@ describe("useSetup", () => { testReact( "returning a render function that takes props", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML( (value, { greeting }) => @@ -144,7 +144,7 @@ describe("useSetup", () => { ); testReact("returning a reactive value", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML( (value) => @@ -188,7 +188,7 @@ describe("useSetup", () => { }); testReact("returning a static value", async (root) => { - const result = await root + const result = root .expectStable() .expectHTML( (value) => diff --git a/packages/react/react/tests/use-starbeam-app.spec.ts b/packages/react/react/tests/use-starbeam-app.spec.ts index c09d171b..733acb12 100644 --- a/packages/react/react/tests/use-starbeam-app.spec.ts +++ b/packages/react/react/tests/use-starbeam-app.spec.ts @@ -16,7 +16,7 @@ describe("useStarbeamApp", () => { async (root) => { let currentApp: ReactApp | null = null; - const result = await root + const result = root .expectStable() .expectHTML((counter) => ``) .render((state) => { diff --git a/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts b/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts index 21f4d5b4..bc159d74 100644 --- a/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts @@ -6,7 +6,7 @@ import { useEffect, useLayoutEffect, useMemo, useState } from "react"; import { expect } from "vitest"; testReact("useResource", async (root) => { - const result = await root + const result = root .expectHTML((value) => `

    isRendering = ${String(value)}

    `) .render((state) => { expect(isRendering(), "isRendering at the top level").toBe(true); diff --git a/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts b/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts index 9f834f2d..5864d9d5 100644 --- a/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts @@ -6,7 +6,7 @@ import { useEffect, useLayoutEffect, useRef, useState } from "react"; testReact( "testReact (testing the test infra)", async (root) => { - await root + root .expectHTML( ({ count, state }) => `

    count = ${count}

    state = ${state}

    ` ) From 93123863b0d81eb8622de352649332ee4203eab5 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 16:04:21 -0700 Subject: [PATCH 45/46] More ci:fix --- packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts b/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts index 5864d9d5..59f6d334 100644 --- a/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/updating-ref.spec.ts @@ -5,7 +5,7 @@ import { useEffect, useLayoutEffect, useRef, useState } from "react"; testReact( "testReact (testing the test infra)", - async (root) => { + (root) => { root .expectHTML( ({ count, state }) => `

    count = ${count}

    state = ${state}

    ` From a166a888373973f449f764fdfc3b54d086f7751f Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 13 Apr 2023 16:12:59 -0700 Subject: [PATCH 46/46] more ci:lint fixes --- packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts b/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts index bc159d74..8e37faf8 100644 --- a/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts +++ b/packages/react/use-strict-lifecycle/tests/is-rendering.spec.ts @@ -5,7 +5,7 @@ import { html, testReact } from "@starbeam-workspace/react-test-utils"; import { useEffect, useLayoutEffect, useMemo, useState } from "react"; import { expect } from "vitest"; -testReact("useResource", async (root) => { +testReact("useResource", (root) => { const result = root .expectHTML((value) => `

    isRendering = ${String(value)}

    `) .render((state) => {