diff --git a/.github/workflows/deployWebSample.yml b/.github/workflows/deployWebSample.yml index bb6c21fdfe..2e7bb610da 100644 --- a/.github/workflows/deployWebSample.yml +++ b/.github/workflows/deployWebSample.yml @@ -52,8 +52,7 @@ jobs: - name: Publish Web SDK Sample Build run: ./build/bin/upload-web-sdk-sample-build.sh env: - GITHUB_USERNAME: ${{ secrets.GIT_WEB_SDK_SAMPLE_USERNAME }} - GITHUB_PASSWORD: ${{ secrets.GIT_WEB_SDK_SAMPLE_PASSWORD }} + GIT_WEB_SDK_SAMPLE_PAT: ${{ secrets.GIT_WEB_SDK_SAMPLE_PAT }} SAMPLE_DIR: ${{ env.SAMPLE_DIR }} - uses: github-actions-up-and-running/pr-comment@v1.0.1 diff --git a/.github/workflows/release-portal-toolkit.yml b/.github/workflows/release-portal-toolkit.yml new file mode 100644 index 0000000000..2aca4a37e5 --- /dev/null +++ b/.github/workflows/release-portal-toolkit.yml @@ -0,0 +1,103 @@ +name: Portal Toolkit Release + +on: + workflow_dispatch: + inputs: + commit: + type: string + description: Commit hash to deploy + default: main + major: + type: number + description: Major version number, X.0.0 + required: true + default: 0 + minor: + type: number + description: Minor version number, 0.X.0 + required: true + default: 0 + patch: + type: number + description: Patch version number, 0.0.X + required: true + default: 0 + rcNumber: + type: number + description: Rc version number, if required, 0.0.0-rc.X + required: false + default: 0 + releaseType: + type: choice + description: What type of release is this? + required: true + options: + - nightly + - rc + - exp + - production + dryRun: + type: boolean + description: When true, no publish will happen + required: true + default: false + +run-name: >- + Release Portal Toolkit ${{ inputs.releaseType }} + ${{ inputs.major }}.${{ inputs.minor }}.${{ inputs.patch }} + ${{ inputs.releaseType == 'rc' && format('-rc.{0}', inputs.rcNumber) || '' }} + by @${{ github.actor }} + +jobs: + portal-toolkit-release: + runs-on: ubuntu-latest + permissions: + id-token: write + defaults: + run: + working-directory: beam-portal-toolkit + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.commit }} + + - name: Use Node.js LTS + uses: actions/setup-node@v4 + with: + node-version: '22.14.0' + registry-url: 'https://registry.npmjs.org' + + - name: Install pnpm + run: npm install -g pnpm@10.8.0 + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Compute version + id: version + run: | + VERSION="${{ inputs.major }}.${{ inputs.minor }}.${{ inputs.patch }}" + if [ "${{ inputs.releaseType }}" == "rc" ]; then + VERSION="${VERSION}-rc.${{ inputs.rcNumber }}" + elif [ "${{ inputs.releaseType }}" != "production" ]; then + VERSION="${VERSION}-${{ inputs.releaseType }}" + fi + NPM_TAG="${{ inputs.releaseType }}" + if [ "${{ inputs.releaseType }}" == "production" ]; then + NPM_TAG="latest" + fi + echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" + echo "NPM_TAG=$NPM_TAG" >> "$GITHUB_OUTPUT" + echo "Computed version: $VERSION (tag: $NPM_TAG)" + + - name: Set package version + run: npm version ${{ steps.version.outputs.VERSION }} --no-git-tag-version + + # prepublishOnly runs sync-components --no-copy && build automatically + - name: Publish to npm + if: ${{ inputs.dryRun == false }} + run: pnpm publish --no-git-checks --provenance --access public --tag ${{ steps.version.outputs.NPM_TAG }} + + - name: Dry run build + if: ${{ inputs.dryRun == true }} + run: pnpm prepublishOnly diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index cfd7202967..0a5ba45f65 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -24,7 +24,7 @@ on: default: 0 rcNumber: type: number - description: Rc version number, if required, 0.0.0-PREVIEW.RCX + description: Rc version number, if required, 0.0.0-rc.X required: false default: 0 releaseType: @@ -51,6 +51,8 @@ run-name: >- jobs: web-sdk-release: runs-on: ubuntu-latest + permissions: + id-token: write defaults: run: working-directory: web @@ -59,38 +61,57 @@ jobs: with: ref: ${{ github.event.inputs.commit }} - # Setup Node.js LTS version 22.14.0 - name: Use Node.js LTS uses: actions/setup-node@v4 with: node-version: '22.14.0' + registry-url: 'https://registry.npmjs.org' - # Install pnpm package manager version 10.8.0 globally - name: Install pnpm run: npm install -g pnpm@10.8.0 - # Install project dependencies using pnpm - name: Install dependencies run: pnpm install --frozen-lockfile - # Run code linter - name: Lint run: pnpm lint - # Run the test suite - name: Test run: pnpm test - + + - name: Compute version + id: version + run: | + VERSION="${{ inputs.major }}.${{ inputs.minor }}.${{ inputs.patch }}" + if [ "${{ inputs.releaseType }}" == "rc" ]; then + VERSION="${VERSION}-rc.${{ inputs.rcNumber }}" + elif [ "${{ inputs.releaseType }}" != "production" ]; then + VERSION="${VERSION}-${{ inputs.releaseType }}" + fi + NPM_TAG="${{ inputs.releaseType }}" + if [ "${{ inputs.releaseType }}" == "production" ]; then + NPM_TAG="latest" + fi + echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" + echo "NPM_TAG=$NPM_TAG" >> "$GITHUB_OUTPUT" + echo "Computed version: $VERSION (tag: $NPM_TAG)" + + - name: Set package version + run: npm version ${{ steps.version.outputs.VERSION }} --no-git-tag-version + + # prepublishOnly runs build automatically + - name: Publish to npm + if: ${{ inputs.dryRun == false }} + run: pnpm publish --no-git-checks --provenance --access public --tag ${{ steps.version.outputs.NPM_TAG }} + - name: Publish Changelog - if: ${{ inputs.dryRun == false }} + if: ${{ inputs.dryRun == false }} run: sh ./../build/bin/upload-changelogs.sh env: COPY_UNITY_SDK: 'false' COPY_CLI: 'false' COPY_WEB_SDK: 'true' - VERSION: >- - ${{ inputs.major }}.${{ inputs.minor }}.${{ inputs.patch }} - ${{ inputs.releaseType == 'rc' && format('-rc.{0}', inputs.rcNumber) || '' }} + VERSION: ${{ steps.version.outputs.VERSION }} GITHUB_USERNAME: ${{ secrets.GIT_CHANGELOGS_USERNAME }} GITHUB_PASSWORD: ${{ secrets.GIT_CHANGELOGS_PASSWORD }} BRANCH: >- @@ -101,6 +122,6 @@ jobs: "production": "production" }')[github.event.inputs.releaseType] }} - # # Run the release command that bumps the version, updates the changelog, and builds the project. - # - name: Run Release - # run: pnpm release + - name: Dry run build + if: ${{ inputs.dryRun == true }} + run: pnpm prepublishOnly diff --git a/.gitignore b/.gitignore index d68f38e043..237ce73e66 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ cli/beamable.templates/.config/dotnet-tools.json /dist /BeamableNugetSource build-number.txt +web-build-number.txt .obsidian @@ -178,4 +179,5 @@ web/.idea web/dist web/docs web/node_modules -web/temp \ No newline at end of file +web/temp + diff --git a/README.md b/README.md index b93d59a8e0..a081948ecb 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,13 @@ Prereqs: `dotnet` (8+), and a POSIX shell for the provided scripts (or use WSL o - `./dev.sh` — builds and publishes local packages into a local NuGet feed consumed by downstream projects (used for fast iteration across CLI, microservices, and Unity SDK). - Run the repo-level scripts from the repository root. See `cli/` README for how to run CLI-specific projects after running the scripts. +### Web local dev (Portal Toolkit & Web SDK) +Prereqs: Node.js 22+, `pnpm`, and Docker. + +- `./setup-web.sh` (run once) — starts a local Verdaccio npm registry and local-unpkg CDN via Docker Compose, resets the build number, and configures npm to resolve `@beamable/*` packages from the local registry. +- `./dev-web.sh` — builds and publishes `@beamable/sdk` and `@beamable/portal-toolkit` to the local Verdaccio registry, then restarts local-unpkg to clear its cache. +- `./teardown-web.sh` — removes the `@beamable/*` registry override from npm config and stops the local Docker stack. + ## Documentation and help - Unity SDK docs: https://help.beamable.com/Unity-Latest/ - CLI docs: https://help.beamable.com/CLI-Latest/ diff --git a/beam-portal-toolkit/.gitignore b/beam-portal-toolkit/.gitignore new file mode 100644 index 0000000000..b7cc5e8f0b --- /dev/null +++ b/beam-portal-toolkit/.gitignore @@ -0,0 +1,5 @@ +.idea +dist +docs +node_modules +temp diff --git a/beam-portal-toolkit/README.md b/beam-portal-toolkit/README.md new file mode 100644 index 0000000000..4be5c80570 --- /dev/null +++ b/beam-portal-toolkit/README.md @@ -0,0 +1,180 @@ +# @beamable/portal-toolkit + +Utilities and type definitions for building Beamable portal extensions. + +- **`Portal.registerExtension()`** — registers your extension with the portal host +- **TypeScript types** for all Beamable web components (`beam-btn`, `beam-data-table`, etc.) +- **Svelte element types** for `.svelte` template autocomplete +- **Re-exports** of `@beamable/sdk` types + +--- + +## Installation + +```bash +npm install @beamable/portal-toolkit +# @beamable/sdk is a peer dependency — install it too +npm install @beamable/sdk +``` + +Because `@beamable/sdk` is injected as a global by the portal host at runtime, mark it external in your bundler: + +```ts +// vite.config.ts +export default { + build: { + rollupOptions: { + external: ['@beamable/sdk'], + }, + }, +}; +``` + +--- + +## Usage + +### Registering an extension + +```ts +import { Portal } from '@beamable/portal-toolkit'; + +Portal.registerExtension({ + beamId: 'MyExtension', + onMount(container, context) { + // context.beam — Promise — the Beamable SDK instance + // context.cid — customer ID + // context.realm — realm string (cid.pid) + container.innerHTML = `

Hello from ${context.realm}

`; + return container; // returned value is passed to onUnmount + }, + onUnmount(instance) { + // tear down your UI + }, +}); +``` + +### Svelte autocomplete + +Add one line to your project's `app.d.ts`: + +```ts +/// +``` + +This gives `.svelte` templates full autocomplete for all `beam-*` components. + +--- + +## Development + +### Syncing web components from Portal + +The custom element definitions live in the Portal repo. When Portal adds or changes components, pull them into this package: + +```bash +# Copies Portal's beam-components.json and regenerates all type files +pnpm sync-components +``` + +By default the script expects Portal to be a sibling directory: + +``` +~/Documents/Github/ + BeamableProduct/ ← this repo + Portal/ ← Portal repo +``` + +Override the path if yours is elsewhere: + +```bash +PORTAL_REPO_PATH=/path/to/Portal pnpm sync-components +``` + +This regenerates: +- `custom-elements.json` — CEM manifest (VS Code HTML IntelliSense) +- `src/generated/globals.ts` — `HTMLElementTagNameMap` augmentations +- `src/generated/svelte-elements.ts` — `SvelteHTMLElements` augmentations +- `src/generated/web-types.json` — JetBrains/WebStorm autocomplete + +Commit all generated files after syncing. + +### Building locally + +```bash +pnpm install +pnpm build +``` + +`prepublishOnly` runs `sync-components --no-copy && build` automatically before publish, so the +generated files are always up to date without re-copying from Portal. + +--- + +## Releasing a new version + +### Step 1 — Sync components (if Portal changed) + +If the Portal repo has new or updated components since the last release, run: + +```bash +pnpm sync-components +``` + +Review the diff, then commit. + +### Step 2 — Update the Portal repo version mapping + +> **This step is required.** The portal host uses a version map to know which toolkit version to load for a given extension. Without this update, extensions referencing the new version will fail to load. + +In the **Portal repo**, update the version mapping file (ask the Portal team for the exact location if unsure) to add an entry for the new toolkit version. + +### Step 3 — Trigger the GitHub Action + +Go to **Actions → Portal Toolkit Release** and click **Run workflow**. Fill in: + +| Field | Notes | +|---|---| +| `major` / `minor` / `patch` | The new semver components | +| `releaseType` | `production` for a stable release, `rc` for a release candidate, `nightly`/`exp` for pre-release | +| `rcNumber` | Only needed when `releaseType` is `rc` | +| `dryRun` | Set `true` to verify the build without publishing | + +The workflow will: +1. Check out the repo at the specified commit +2. Set the package version from the inputs +3. Run `prepublishOnly` (sync + build) +4. Publish to npm with provenance attestation + +### Version format + +| `releaseType` | npm tag | Version example | +|---|---|---| +| `production` | `latest` | `1.2.3` | +| `rc` | `rc` | `1.2.3-rc.1` | +| `nightly` | `nightly` | `1.2.3-nightly` | +| `exp` | `exp` | `1.2.3-exp` | + +### Manual publish (first-time or emergency) + +```bash +cd beam-portal-toolkit +nvm use 22.14.0 && corepack enable +pnpm install +# optionally bump version first: +# npm version 0.2.0 --no-git-tag-version +pnpm publish --access public +``` + +You must be logged in to npm (`npm login`) with publish rights to the `@beamable` org and have an automation token configured (see npm → Access Tokens → Granular Access Token with "bypass 2FA"). + +--- + +## Package exports + +| Import path | Contents | +|---|---| +| `@beamable/portal-toolkit` | `Portal` namespace, all `@beamable/sdk` types, web component globals | +| `@beamable/portal-toolkit/svelte` | `SvelteHTMLElements` augmentations (triple-slash reference only) | +| `@beamable/portal-toolkit/custom-elements.json` | CEM manifest | +| `@beamable/portal-toolkit/web-types.json` | JetBrains web-types | diff --git a/beam-portal-toolkit/custom-elements.json b/beam-portal-toolkit/custom-elements.json new file mode 100644 index 0000000000..6375903596 --- /dev/null +++ b/beam-portal-toolkit/custom-elements.json @@ -0,0 +1,1655 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "plugins/vue-register-components.js", + "declarations": [ + { + "kind": "custom-element", + "tagName": "beam-btn", + "name": "BeamBtn", + "description": "A Material Design button. Supports outlined, text, icon, fab, and loading variants.", + "customElement": true, + "attributes": [ + { + "name": "color", + "type": { + "text": "string" + }, + "description": "Fill or text color. Accepts a CSS color or theme color name (e.g. `primary`, `secondary`, `error`)." + }, + { + "name": "outlined", + "type": { + "text": "boolean" + }, + "description": "Renders with a border and transparent background." + }, + { + "name": "text", + "type": { + "text": "boolean" + }, + "description": "Renders as a flat text button with no background or border." + }, + { + "name": "block", + "type": { + "text": "boolean" + }, + "description": "Expands the button to fill its container's full width." + }, + { + "name": "disabled", + "type": { + "text": "boolean" + } + }, + { + "name": "small", + "type": { + "text": "boolean" + } + }, + { + "name": "large", + "type": { + "text": "boolean" + } + }, + { + "name": "x-small", + "fieldName": "xSmall", + "type": { + "text": "boolean" + } + }, + { + "name": "x-large", + "fieldName": "xLarge", + "type": { + "text": "boolean" + } + }, + { + "name": "icon", + "type": { + "text": "boolean" + }, + "description": "Renders as a square icon button sized to fit a single icon." + }, + { + "name": "fab", + "type": { + "text": "boolean" + }, + "description": "Renders as a circular floating action button." + }, + { + "name": "tile", + "type": { + "text": "boolean" + } + }, + { + "name": "rounded", + "type": { + "text": "boolean" + } + }, + { + "name": "depressed", + "type": { + "text": "boolean" + } + }, + { + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "name": "loading", + "type": { + "text": "boolean" + }, + "description": "Shows a loading spinner and disables the button." + }, + { + "name": "href", + "type": { + "text": "string" + }, + "description": "Renders the button as an anchor tag pointing to this URL." + }, + { + "name": "target", + "type": { + "text": "string" + }, + "description": "The `target` attribute forwarded to the anchor tag when `href` is set." + }, + { + "name": "type", + "type": { + "text": "string" + }, + "description": "The HTML button `type` attribute: `button`, `submit`, or `reset`." + }, + { + "name": "elevation", + "type": { + "text": "string" + } + } + ], + "members": [ + { + "kind": "field", + "name": "color", + "type": { + "text": "string" + }, + "description": "Fill or text color. Accepts a CSS color or theme color name (e.g. `primary`, `secondary`, `error`)." + }, + { + "kind": "field", + "name": "outlined", + "type": { + "text": "boolean" + }, + "description": "Renders with a border and transparent background." + }, + { + "kind": "field", + "name": "text", + "type": { + "text": "boolean" + }, + "description": "Renders as a flat text button with no background or border." + }, + { + "kind": "field", + "name": "block", + "type": { + "text": "boolean" + }, + "description": "Expands the button to fill its container's full width." + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "small", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "large", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "xSmall", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "xLarge", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "icon", + "type": { + "text": "boolean" + }, + "description": "Renders as a square icon button sized to fit a single icon." + }, + { + "kind": "field", + "name": "fab", + "type": { + "text": "boolean" + }, + "description": "Renders as a circular floating action button." + }, + { + "kind": "field", + "name": "tile", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "rounded", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "depressed", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "loading", + "type": { + "text": "boolean" + }, + "description": "Shows a loading spinner and disables the button." + }, + { + "kind": "field", + "name": "href", + "type": { + "text": "string" + }, + "description": "Renders the button as an anchor tag pointing to this URL." + }, + { + "kind": "field", + "name": "target", + "type": { + "text": "string" + }, + "description": "The `target` attribute forwarded to the anchor tag when `href` is set." + }, + { + "kind": "field", + "name": "type", + "type": { + "text": "string" + }, + "description": "The HTML button `type` attribute: `button`, `submit`, or `reset`." + }, + { + "kind": "field", + "name": "elevation", + "type": { + "text": "string" + } + } + ], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-icon", + "name": "BeamIcon", + "description": "Renders a Material Design icon by name. Pass the icon name via the `icon` prop or as default slot content.", + "customElement": true, + "attributes": [ + { + "name": "icon", + "type": { + "text": "string" + }, + "description": "The Material Design icon name (e.g. `mdi-home`). Can also be passed as slot content." + }, + { + "name": "color", + "type": { + "text": "string" + }, + "description": "Icon color. Accepts a CSS color or theme color name (e.g. `primary`, `error`)." + }, + { + "name": "small", + "type": { + "text": "boolean" + } + }, + { + "name": "large", + "type": { + "text": "boolean" + } + }, + { + "name": "x-small", + "fieldName": "xSmall", + "type": { + "text": "boolean" + } + }, + { + "name": "x-large", + "fieldName": "xLarge", + "type": { + "text": "boolean" + } + }, + { + "name": "dense", + "type": { + "text": "boolean" + } + }, + { + "name": "disabled", + "type": { + "text": "boolean" + } + }, + { + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "name": "left", + "type": { + "text": "boolean" + }, + "description": "Adds right margin — use when the icon precedes inline text." + }, + { + "name": "right", + "type": { + "text": "boolean" + }, + "description": "Adds left margin — use when the icon follows inline text." + } + ], + "members": [ + { + "kind": "field", + "name": "icon", + "type": { + "text": "string" + }, + "description": "The Material Design icon name (e.g. `mdi-home`). Can also be passed as slot content." + }, + { + "kind": "field", + "name": "color", + "type": { + "text": "string" + }, + "description": "Icon color. Accepts a CSS color or theme color name (e.g. `primary`, `error`)." + }, + { + "kind": "field", + "name": "small", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "large", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "xSmall", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "xLarge", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "dense", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "left", + "type": { + "text": "boolean" + }, + "description": "Adds right margin — use when the icon precedes inline text." + }, + { + "kind": "field", + "name": "right", + "type": { + "text": "boolean" + }, + "description": "Adds left margin — use when the icon follows inline text." + } + ], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-chip", + "name": "BeamChip", + "description": "A small label element used for tags, filters, or status indicators. Supports closeable, outlined, and pill variants.", + "customElement": true, + "attributes": [ + { + "name": "color", + "type": { + "text": "string" + }, + "description": "Fill color. Accepts a CSS color or theme color name (e.g. `primary`, `error`)." + }, + { + "name": "outlined", + "type": { + "text": "boolean" + } + }, + { + "name": "small", + "type": { + "text": "boolean" + } + }, + { + "name": "large", + "type": { + "text": "boolean" + } + }, + { + "name": "x-small", + "fieldName": "xSmall", + "type": { + "text": "boolean" + } + }, + { + "name": "close", + "type": { + "text": "boolean" + }, + "description": "Shows a dismiss icon on the chip. Listen for the `click:close` event to handle removal." + }, + { + "name": "disabled", + "type": { + "text": "boolean" + } + }, + { + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "name": "label", + "type": { + "text": "boolean" + }, + "description": "Renders as a square chip rather than rounded." + }, + { + "name": "pill", + "type": { + "text": "boolean" + }, + "description": "Renders with fully rounded (pill-shaped) ends." + } + ], + "members": [ + { + "kind": "field", + "name": "color", + "type": { + "text": "string" + }, + "description": "Fill color. Accepts a CSS color or theme color name (e.g. `primary`, `error`)." + }, + { + "kind": "field", + "name": "outlined", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "small", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "large", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "xSmall", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "close", + "type": { + "text": "boolean" + }, + "description": "Shows a dismiss icon on the chip. Listen for the `click:close` event to handle removal." + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "label", + "type": { + "text": "boolean" + }, + "description": "Renders as a square chip rather than rounded." + }, + { + "kind": "field", + "name": "pill", + "type": { + "text": "boolean" + }, + "description": "Renders with fully rounded (pill-shaped) ends." + } + ], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-alert", + "name": "BeamAlert", + "description": "Displays a contextual message to the user. Use the `type` prop for semantic variants: `success`, `info`, `warning`, or `error`.", + "customElement": true, + "attributes": [ + { + "name": "color", + "type": { + "text": "string" + }, + "description": "Fill color. Overrides the color implied by `type`." + }, + { + "name": "type", + "type": { + "text": "string" + }, + "description": "Semantic variant: `success`, `info`, `warning`, or `error`. Sets icon and color automatically." + }, + { + "name": "outlined", + "type": { + "text": "boolean" + } + }, + { + "name": "text", + "type": { + "text": "boolean" + } + }, + { + "name": "dense", + "type": { + "text": "boolean" + } + }, + { + "name": "dismissible", + "type": { + "text": "boolean" + }, + "description": "Shows a close button. Listen for the `input` event (emits `false`) to handle dismissal." + }, + { + "name": "icon", + "type": { + "text": "string" + }, + "description": "Overrides the default icon for the current `type`. Pass `false` to remove the icon." + }, + { + "name": "border", + "type": { + "text": "string" + }, + "description": "Adds a colored border on one side: `top`, `right`, `bottom`, or `left`." + }, + { + "name": "elevation", + "type": { + "text": "string" + } + }, + { + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "name": "prominent", + "type": { + "text": "boolean" + }, + "description": "Increases the alert height and renders the icon at a larger size." + }, + { + "name": "tile", + "type": { + "text": "boolean" + } + } + ], + "members": [ + { + "kind": "field", + "name": "color", + "type": { + "text": "string" + }, + "description": "Fill color. Overrides the color implied by `type`." + }, + { + "kind": "field", + "name": "type", + "type": { + "text": "string" + }, + "description": "Semantic variant: `success`, `info`, `warning`, or `error`. Sets icon and color automatically." + }, + { + "kind": "field", + "name": "outlined", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "text", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "dense", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "dismissible", + "type": { + "text": "boolean" + }, + "description": "Shows a close button. Listen for the `input` event (emits `false`) to handle dismissal." + }, + { + "kind": "field", + "name": "icon", + "type": { + "text": "string" + }, + "description": "Overrides the default icon for the current `type`. Pass `false` to remove the icon." + }, + { + "kind": "field", + "name": "border", + "type": { + "text": "string" + }, + "description": "Adds a colored border on one side: `top`, `right`, `bottom`, or `left`." + }, + { + "kind": "field", + "name": "elevation", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "prominent", + "type": { + "text": "boolean" + }, + "description": "Increases the alert height and renders the icon at a larger size." + }, + { + "kind": "field", + "name": "tile", + "type": { + "text": "boolean" + } + } + ], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-card", + "name": "BeamCard", + "description": "A surface container with elevation and rounded corners for grouping related content.", + "customElement": true, + "attributes": [ + { + "name": "elevation", + "type": { + "text": "string" + }, + "description": "Shadow depth (0–24). Maps to the `elevation-N` CSS class." + } + ], + "members": [ + { + "kind": "field", + "name": "elevation", + "type": { + "text": "string" + }, + "description": "Shadow depth (0–24). Maps to the `elevation-N` CSS class." + } + ], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ], + "cssClasses": [ + { + "name": "v-card" + }, + { + "name": "v-sheet" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-card-title", + "name": "BeamCardTitle", + "description": "The title region of a beam-card. Renders with card title typography.", + "customElement": true, + "attributes": [], + "members": [], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ], + "cssClasses": [ + { + "name": "v-card__title" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-card-subtitle", + "name": "BeamCardSubtitle", + "description": "The subtitle region of a beam-card. Renders with card subtitle typography.", + "customElement": true, + "attributes": [], + "members": [], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ], + "cssClasses": [ + { + "name": "v-card__subtitle" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-card-text", + "name": "BeamCardText", + "description": "The body content region of a beam-card. Adds standard card padding.", + "customElement": true, + "attributes": [], + "members": [], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ], + "cssClasses": [ + { + "name": "v-card__text" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-card-actions", + "name": "BeamCardActions", + "description": "The actions region of a beam-card. Aligns action buttons at the bottom of the card.", + "customElement": true, + "attributes": [], + "members": [], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ], + "cssClasses": [ + { + "name": "v-card__actions" + } + ] + }, + { + "kind": "custom-element", + "tagName": "beam-data-table", + "name": "BeamDataTable", + "description": "A full-featured data table with sorting, pagination, filtering, and row selection.", + "customElement": true, + "attributes": [ + { + "name": "headers", + "type": { + "text": "array" + }, + "description": "Column definitions. Each item requires a `text` (display label) and `value` (row data key)." + }, + { + "name": "items", + "type": { + "text": "array" + }, + "description": "Array of row data objects. Each object's keys should match the `value` fields in `headers`." + }, + { + "name": "items-per-page", + "fieldName": "itemsPerPage", + "type": { + "text": "string" + }, + "description": "Number of rows shown per page. Set to `-1` to show all rows. Defaults to `10`." + }, + { + "name": "loading", + "type": { + "text": "boolean" + }, + "description": "Shows a loading bar above the table." + }, + { + "name": "search", + "type": { + "text": "string" + }, + "description": "Filters visible rows to those matching this string." + }, + { + "name": "sort-by", + "fieldName": "sortBy", + "type": { + "text": "string" + }, + "description": "The column `value` key to sort by." + }, + { + "name": "sort-desc", + "fieldName": "sortDesc", + "type": { + "text": "string" + } + }, + { + "name": "multi-sort", + "fieldName": "multiSort", + "type": { + "text": "boolean" + } + }, + { + "name": "must-sort", + "fieldName": "mustSort", + "type": { + "text": "boolean" + } + }, + { + "name": "show-select", + "fieldName": "showSelect", + "type": { + "text": "boolean" + }, + "description": "Adds a checkbox column for row selection. Use `value` to read or set the selected rows." + }, + { + "name": "single-select", + "fieldName": "singleSelect", + "type": { + "text": "boolean" + } + }, + { + "name": "value", + "type": { + "text": "string" + }, + "description": "The currently selected rows when `showSelect` is true." + }, + { + "name": "dense", + "type": { + "text": "boolean" + } + }, + { + "name": "fixed-header", + "fieldName": "fixedHeader", + "type": { + "text": "boolean" + }, + "description": "Fixes the header row so only the body scrolls when `height` is set." + }, + { + "name": "height", + "type": { + "text": "string" + }, + "description": "Sets a fixed height on the table. Required for `fixedHeader` to take effect." + }, + { + "name": "hide-default-header", + "fieldName": "hideDefaultHeader", + "type": { + "text": "boolean" + } + }, + { + "name": "hide-default-footer", + "fieldName": "hideDefaultFooter", + "type": { + "text": "boolean" + } + }, + { + "name": "no-data-text", + "fieldName": "noDataText", + "type": { + "text": "string" + }, + "description": "Message shown when `items` is empty." + }, + { + "name": "no-results-text", + "fieldName": "noResultsText", + "type": { + "text": "string" + }, + "description": "Message shown when `search` produces no matches." + }, + { + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "name": "item-key", + "fieldName": "itemKey", + "type": { + "text": "string" + }, + "description": "The row property used as a unique key. Defaults to `id`." + }, + { + "name": "item-class", + "fieldName": "itemClass", + "type": { + "text": "string" + } + }, + { + "name": "page", + "type": { + "text": "string" + }, + "description": "The current page number (1-based)." + }, + { + "name": "server-items-length", + "fieldName": "serverItemsLength", + "type": { + "text": "string" + }, + "description": "Total number of items on the server. Required for server-side pagination." + }, + { + "name": "disable-pagination", + "fieldName": "disablePagination", + "type": { + "text": "boolean" + } + }, + { + "name": "disable-sort", + "fieldName": "disableSort", + "type": { + "text": "boolean" + } + }, + { + "name": "show-expand", + "fieldName": "showExpand", + "type": { + "text": "boolean" + }, + "description": "Adds an expand toggle column. Use `expanded` to read or set expanded rows." + }, + { + "name": "expanded", + "type": { + "text": "string" + }, + "description": "Array of currently expanded row objects." + }, + { + "name": "group-by", + "fieldName": "groupBy", + "type": { + "text": "string" + } + }, + { + "name": "group-desc", + "fieldName": "groupDesc", + "type": { + "text": "string" + } + }, + { + "name": "show-group-by", + "fieldName": "showGroupBy", + "type": { + "text": "boolean" + } + }, + { + "name": "mobile-breakpoint", + "fieldName": "mobileBreakpoint", + "type": { + "text": "string" + } + }, + { + "name": "loader-height", + "fieldName": "loaderHeight", + "type": { + "text": "string" + } + }, + { + "name": "loading-text", + "fieldName": "loadingText", + "type": { + "text": "string" + } + }, + { + "name": "footer-props", + "fieldName": "footerProps", + "type": { + "text": "string" + }, + "description": "Props forwarded to the footer pagination control." + }, + { + "name": "header-props", + "fieldName": "headerProps", + "type": { + "text": "string" + }, + "description": "Props forwarded to the header row." + }, + { + "name": "calculate-widths", + "fieldName": "calculateWidths", + "type": { + "text": "boolean" + } + }, + { + "name": "caption", + "type": { + "text": "string" + } + } + ], + "members": [ + { + "kind": "field", + "name": "headers", + "type": { + "text": "array" + }, + "description": "Column definitions. Each item requires a `text` (display label) and `value` (row data key)." + }, + { + "kind": "field", + "name": "items", + "type": { + "text": "array" + }, + "description": "Array of row data objects. Each object's keys should match the `value` fields in `headers`." + }, + { + "kind": "field", + "name": "itemsPerPage", + "type": { + "text": "string" + }, + "description": "Number of rows shown per page. Set to `-1` to show all rows. Defaults to `10`." + }, + { + "kind": "field", + "name": "loading", + "type": { + "text": "boolean" + }, + "description": "Shows a loading bar above the table." + }, + { + "kind": "field", + "name": "search", + "type": { + "text": "string" + }, + "description": "Filters visible rows to those matching this string." + }, + { + "kind": "field", + "name": "sortBy", + "type": { + "text": "string" + }, + "description": "The column `value` key to sort by." + }, + { + "kind": "field", + "name": "sortDesc", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "multiSort", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "mustSort", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "showSelect", + "type": { + "text": "boolean" + }, + "description": "Adds a checkbox column for row selection. Use `value` to read or set the selected rows." + }, + { + "kind": "field", + "name": "singleSelect", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "string" + }, + "description": "The currently selected rows when `showSelect` is true." + }, + { + "kind": "field", + "name": "dense", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "fixedHeader", + "type": { + "text": "boolean" + }, + "description": "Fixes the header row so only the body scrolls when `height` is set." + }, + { + "kind": "field", + "name": "height", + "type": { + "text": "string" + }, + "description": "Sets a fixed height on the table. Required for `fixedHeader` to take effect." + }, + { + "kind": "field", + "name": "hideDefaultHeader", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "hideDefaultFooter", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "noDataText", + "type": { + "text": "string" + }, + "description": "Message shown when `items` is empty." + }, + { + "kind": "field", + "name": "noResultsText", + "type": { + "text": "string" + }, + "description": "Message shown when `search` produces no matches." + }, + { + "kind": "field", + "name": "dark", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "light", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "itemKey", + "type": { + "text": "string" + }, + "description": "The row property used as a unique key. Defaults to `id`." + }, + { + "kind": "field", + "name": "itemClass", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "page", + "type": { + "text": "string" + }, + "description": "The current page number (1-based)." + }, + { + "kind": "field", + "name": "serverItemsLength", + "type": { + "text": "string" + }, + "description": "Total number of items on the server. Required for server-side pagination." + }, + { + "kind": "field", + "name": "disablePagination", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "disableSort", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "showExpand", + "type": { + "text": "boolean" + }, + "description": "Adds an expand toggle column. Use `expanded` to read or set expanded rows." + }, + { + "kind": "field", + "name": "expanded", + "type": { + "text": "string" + }, + "description": "Array of currently expanded row objects." + }, + { + "kind": "field", + "name": "groupBy", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "groupDesc", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "showGroupBy", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "mobileBreakpoint", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "loaderHeight", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "loadingText", + "type": { + "text": "string" + } + }, + { + "kind": "field", + "name": "footerProps", + "type": { + "text": "string" + }, + "description": "Props forwarded to the footer pagination control." + }, + { + "kind": "field", + "name": "headerProps", + "type": { + "text": "string" + }, + "description": "Props forwarded to the header row." + }, + { + "kind": "field", + "name": "calculateWidths", + "type": { + "text": "boolean" + } + }, + { + "kind": "field", + "name": "caption", + "type": { + "text": "string" + } + } + ], + "slots": [ + { + "name": "", + "description": "Default slot" + } + ] + } + ], + "exports": [ + { + "kind": "custom-element-definition", + "name": "beam-btn", + "declaration": { + "name": "BeamBtn" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-icon", + "declaration": { + "name": "BeamIcon" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-chip", + "declaration": { + "name": "BeamChip" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-alert", + "declaration": { + "name": "BeamAlert" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-card", + "declaration": { + "name": "BeamCard" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-card-title", + "declaration": { + "name": "BeamCardTitle" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-card-subtitle", + "declaration": { + "name": "BeamCardSubtitle" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-card-text", + "declaration": { + "name": "BeamCardText" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-card-actions", + "declaration": { + "name": "BeamCardActions" + } + }, + { + "kind": "custom-element-definition", + "name": "beam-data-table", + "declaration": { + "name": "BeamDataTable" + } + } + ] + } + ] +} diff --git a/beam-portal-toolkit/package-lock.json b/beam-portal-toolkit/package-lock.json new file mode 100644 index 0000000000..f26eaf57cc --- /dev/null +++ b/beam-portal-toolkit/package-lock.json @@ -0,0 +1,1441 @@ +{ + "name": "@beamable/portal-toolkit", + "version": "0.1.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@beamable/portal-toolkit", + "version": "0.1.1", + "license": "MIT", + "dependencies": { + "beamable-sdk": "0.6.0" + }, + "devDependencies": { + "svelte": "^5.0.0", + "tsdown": "^0.16.5", + "typescript": "^5.8.3" + }, + "engines": { + "node": ">=22.14.0" + }, + "peerDependencies": { + "svelte": ">=4.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + } + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", + "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.99.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.99.0.tgz", + "integrity": "sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.52.tgz", + "integrity": "sha512-MBGIgysimZPqTDcLXI+i9VveijkP5C3EAncEogXhqfax6YXj1Tr2LY3DVuEOMIjWfMPMhtQSPup4fSTAmgjqIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.52.tgz", + "integrity": "sha512-MmKeoLnKu1d9j6r19K8B+prJnIZ7u+zQ+zGQ3YHXGnr41rzE3eqQLovlkvoZnRoxDGPA4ps0pGiwXy6YE3lJyg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.52.tgz", + "integrity": "sha512-qpHedvQBmIjT8zdnjN3nWPR2qjQyJttbXniCEKKdHeAbZG9HyNPBUzQF7AZZGwmS9coQKL+hWg9FhWzh2dZ2IA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.52.tgz", + "integrity": "sha512-dDp7WbPapj/NVW0LSiH/CLwMhmLwwKb3R7mh2kWX+QW85X1DGVnIEyKh9PmNJjB/+suG1dJygdtdNPVXK1hylg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.52.tgz", + "integrity": "sha512-9e4l6vy5qNSliDPqNfR6CkBOAx6PH7iDV4OJiEJzajajGrVy8gc/IKKJUsoE52G8ud8MX6r3PMl97NfwgOzB7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.52.tgz", + "integrity": "sha512-V48oDR84feRU2KRuzpALp594Uqlx27+zFsT6+BgTcXOtu7dWy350J1G28ydoCwKB+oxwsRPx2e7aeQnmd3YJbQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.52.tgz", + "integrity": "sha512-ENLmSQCWqSA/+YN45V2FqTIemg7QspaiTjlm327eUAMeOLdqmSOVVyrQexJGNTQ5M8sDYCgVAig2Kk01Ggmqaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.11.tgz", + "integrity": "sha512-ZlFgw46NOAGMgcdvdYwAGu2Q+SLFA9LzbJLW+iyMOJyhj5wk6P3KEE9Gct4xWwSzFoPI7JCdYmYMzVtlgQ+zfw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.11.tgz", + "integrity": "sha512-hIOYmuT6ofM4K04XAZd3OzMySEO4K0/nc9+jmNcxNAxRi6c5UWpqfw3KMFV4MVFWL+jQsSh+bGw2VqmaPMTLyw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.52.tgz", + "integrity": "sha512-klahlb2EIFltSUubn/VLjuc3qxp1E7th8ukayPfdkcKvvYcQ5rJztgx8JsJSuAKVzKtNTqUGOhy4On71BuyV8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.52.tgz", + "integrity": "sha512-UuA+JqQIgqtkgGN2c/AQ5wi8M6mJHrahz/wciENPTeI6zEIbbLGoth5XN+sQe2pJDejEVofN9aOAp0kaazwnVg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.52.tgz", + "integrity": "sha512-1BNQW8u4ro8bsN1+tgKENJiqmvc+WfuaUhXzMImOVSMw28pkBKdfZtX2qJPADV3terx+vNJtlsgSGeb3+W6Jiw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.52.tgz", + "integrity": "sha512-K/p7clhCqJOQpXGykrFaBX2Dp9AUVIDHGc+PtFGBwg7V+mvBTv/tsm3LC3aUmH02H2y3gz4y+nUTQ0MLpofEEg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.52.tgz", + "integrity": "sha512-a4EkXBtnYYsKipjS7QOhEBM4bU5IlR9N1hU+JcVEVeuTiaslIyhWVKsvf7K2YkQHyVAJ+7/A9BtrGqORFcTgng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-ia32-msvc": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.52.tgz", + "integrity": "sha512-5ZXcYyd4GxPA6QfbGrNcQjmjbuLGvfz6728pZMsQvGHI+06LT06M6TPtXvFvLgXtexc+OqvFe1yAIXJU1gob/w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.52.tgz", + "integrity": "sha512-tzpnRQXJrSzb8Z9sm97UD3cY0toKOImx+xRKsDLX4zHaAlRXWh7jbaKBePJXEN7gNw7Nm03PBNwphdtA8KSUYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.52.tgz", + "integrity": "sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz", + "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "8.57.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.2.tgz", + "integrity": "sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/aria-query": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/beamable-sdk": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/beamable-sdk/-/beamable-sdk-0.6.0.tgz", + "integrity": "sha512-hWer2//p7XCw01uMg3bebjd7155dcM4bRkbwt54sshMq42QTNVz5PD1jOrxYJKRScmZRzC6c0yp3EQpCsncUnw==", + "license": "MIT", + "engines": { + "node": ">=22.14.0" + } + }, + "node_modules/birpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devalue": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz", + "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dts-resolver": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.3.tgz", + "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } + } + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esrap": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.4.tgz", + "integrity": "sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@typescript-eslint/types": "^8.2.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.6" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-beta.52", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.52.tgz", + "integrity": "sha512-Hbnpljue+JhMJrlOjQ1ixp9me7sUec7OjFvS+A1Qm8k8Xyxmw3ZhxFu7LlSXW1s9AX3POE9W9o2oqCEeR5uDmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.99.0", + "@rolldown/pluginutils": "1.0.0-beta.52" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.52", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.52", + "@rolldown/binding-darwin-x64": "1.0.0-beta.52", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.52", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.52", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.52", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.52", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.52", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.52", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.52", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.52", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.52", + "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.52", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.52" + } + }, + "node_modules/rolldown-plugin-dts": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.18.4.tgz", + "integrity": "sha512-7UpdiICFd/BhdjKtDPeakCFRk6pbkTGFe0Z6u01egt4c8aoO+JoPGF1Smc+JRuCH2s5j5hBdteBi0e10G0xQdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.28.5", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "ast-kit": "^2.2.0", + "birpc": "^4.0.0", + "dts-resolver": "^2.1.3", + "get-tsconfig": "^4.13.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@ts-macro/tsc": "^0.3.6", + "@typescript/native-preview": ">=7.0.0-dev.20250601.1", + "rolldown": "^1.0.0-beta.51", + "typescript": "^5.0.0", + "vue-tsc": "~3.1.0" + }, + "peerDependenciesMeta": { + "@ts-macro/tsc": { + "optional": true + }, + "@typescript/native-preview": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/svelte": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.0.tgz", + "integrity": "sha512-SThllKq6TRMBwPtat7ASnm/9CDXnIhBR0NPGw0ujn2DVYx9rVwsPZxDaDQcYGdUz/3BYVsCzdq7pZarRQoGvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", + "acorn": "^8.12.1", + "aria-query": "5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "devalue": "^5.6.4", + "esm-env": "^1.2.1", + "esrap": "^2.2.2", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tsdown": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.16.8.tgz", + "integrity": "sha512-6ANw9mgU9kk7SvTBKvpDu/DVJeAFECiLUSeL5M7f5Nm5H97E7ybxmXT4PQ23FySYn32y6OzjoAH/lsWCbGzfLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.2.0", + "cac": "^6.7.14", + "chokidar": "^5.0.0", + "diff": "^8.0.2", + "empathic": "^2.0.0", + "hookable": "^5.5.3", + "obug": "^2.1.1", + "rolldown": "1.0.0-beta.52", + "rolldown-plugin-dts": "^0.18.1", + "semver": "^7.7.3", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tree-kill": "^1.2.2", + "unconfig-core": "^7.4.1", + "unrun": "^0.2.13" + }, + "bin": { + "tsdown": "dist/run.mjs" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@arethetypeswrong/core": "^0.18.1", + "@vitejs/devtools": "^0.0.0-alpha.18", + "publint": "^0.3.0", + "typescript": "^5.0.0", + "unplugin-lightningcss": "^0.4.0", + "unplugin-unused": "^0.5.0" + }, + "peerDependenciesMeta": { + "@arethetypeswrong/core": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "publint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "unplugin-lightningcss": { + "optional": true + }, + "unplugin-unused": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unconfig-core": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.5.0.tgz", + "integrity": "sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unrun": { + "version": "0.2.33", + "resolved": "https://registry.npmjs.org/unrun/-/unrun-0.2.33.tgz", + "integrity": "sha512-urXTjZHOHS6lMnatQerLcBpcTsaKZYGuu9aSZ+HlNfCApkiINRbj7YecC9h9hdZroMT4WQ4KVyzHfBqHKuFX9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "rolldown": "1.0.0-rc.11" + }, + "bin": { + "unrun": "dist/cli.mjs" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/Gugustinette" + }, + "peerDependencies": { + "synckit": "^0.11.11" + }, + "peerDependenciesMeta": { + "synckit": { + "optional": true + } + } + }, + "node_modules/unrun/node_modules/@oxc-project/types": { + "version": "0.122.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", + "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.11.tgz", + "integrity": "sha512-SJ+/g+xNnOh6NqYxD0V3uVN4W3VfnrGsC9/hoglicgTNfABFG9JjISvkkU0dNY84MNHLWyOgxP9v9Y9pX4S7+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.11.tgz", + "integrity": "sha512-7WQgR8SfOPwmDZGFkThUvsmd/nwAWv91oCO4I5LS7RKrssPZmOt7jONN0cW17ydGC1n/+puol1IpoieKqQidmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.11.tgz", + "integrity": "sha512-39Ks6UvIHq4rEogIfQBoBRusj0Q0nPVWIvqmwBLaT6aqQGIakHdESBVOPRRLacy4WwUPIx4ZKzfZ9PMW+IeyUQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.11.tgz", + "integrity": "sha512-jfsm0ZHfhiqrvWjJAmzsqiIFPz5e7mAoCOPBNTcNgkiid/LaFKiq92+0ojH+nmJmKYkre4t71BWXUZDNp7vsag==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.11.tgz", + "integrity": "sha512-zjQaUtSyq1nVe3nxmlSCuR96T1LPlpvmJ0SZy0WJFEsV4kFbXcq2u68L4E6O0XeFj4aex9bEauqjW8UQBeAvfQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.11.tgz", + "integrity": "sha512-WMW1yE6IOnehTcFE9eipFkm3XN63zypWlrJQ2iF7NrQ9b2LDRjumFoOGJE8RJJTJCTBAdmLMnJ8uVitACUUo1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.11.tgz", + "integrity": "sha512-jfndI9tsfm4APzjNt6QdBkYwre5lRPUgHeDHoI7ydKUuJvz3lZeCfMsI56BZj+7BYqiKsJm7cfd/6KYV7ubrBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.11.tgz", + "integrity": "sha512-qXBQQO9OvkjjQPLdUVr7Nr2t3QTZI7s4KZtfw7HzBgjbmAPSFwSv4rmET9lLSgq3rH/ndA3ngv3Qb8l2njoPNA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.11.tgz", + "integrity": "sha512-/tpFfoSTzUkH9LPY+cYbqZBDyyX62w5fICq9qzsHLL8uTI6BHip3Q9Uzft0wylk/i8OOwKik8OxW+QAhDmzwmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.11.tgz", + "integrity": "sha512-mcp3Rio2w72IvdZG0oQ4bM2c2oumtwHfUfKncUM6zGgz0KgPz4YmDPQfnXEiY5t3+KD/i8HG2rOB/LxdmieK2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.11.tgz", + "integrity": "sha512-LXk5Hii1Ph9asuGRjBuz8TUxdc1lWzB7nyfdoRgI0WGPZKmCxvlKk8KfYysqtr4MfGElu/f/pEQRh8fcEgkrWw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.11.tgz", + "integrity": "sha512-dDwf5otnx0XgRY1yqxOC4ITizcdzS/8cQ3goOWv3jFAo4F+xQYni+hnMuO6+LssHHdJW7+OCVL3CoU4ycnh35Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.11.tgz", + "integrity": "sha512-LN4/skhSggybX71ews7dAj6r2geaMJfm3kMbK2KhFMg9B10AZXnKoLCVVgzhMHL0S+aKtr4p8QbAW8k+w95bAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unrun/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.11.tgz", + "integrity": "sha512-xQO9vbwBecJRv9EUcQ/y0dzSTJgA7Q6UVN7xp6B81+tBGSLVAK03yJ9NkJaUA7JFD91kbjxRSC/mDnmvXzbHoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrun/node_modules/rolldown": { + "version": "1.0.0-rc.11", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.11.tgz", + "integrity": "sha512-NRjoKMusSjfRbSYiH3VSumlkgFe7kYAa3pzVOsVYVFY3zb5d7nS+a3KGQ7hJKXuYWbzJKPVQ9Wxq2UvyK+ENpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.122.0", + "@rolldown/pluginutils": "1.0.0-rc.11" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.11", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.11", + "@rolldown/binding-darwin-x64": "1.0.0-rc.11", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.11", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.11", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.11", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.11", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.11", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.11", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.11", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.11", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.11", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.11", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.11", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.11" + } + }, + "node_modules/zimmerframe": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/beam-portal-toolkit/package.json b/beam-portal-toolkit/package.json new file mode 100644 index 0000000000..fcdc66c5d0 --- /dev/null +++ b/beam-portal-toolkit/package.json @@ -0,0 +1,64 @@ +{ + "name": "@beamable/portal-toolkit", + "version": "0.1.3", + "description": "Beamable Portal Toolkit — utilities and web component types for the Beamable portal plugin system", + "main": "dist/index.cjs", + "module": "dist/index.mjs", + "types": "dist/types/index.d.ts", + "customElements": "custom-elements.json", + "web-types": "src/generated/web-types.json", + "author": "Beamable", + "license": "MIT", + "packageManager": "pnpm@10.8.0", + "engines": { + "node": ">=22.14.0" + }, + "files": [ + "dist", + "custom-elements.json", + "src/generated" + ], + "scripts": { + "build": "tsdown", + "dev": "tsdown --watch", + "sync-components": "node scripts/sync-components.mjs", + "prepublishOnly": "pnpm sync-components --no-copy && pnpm build" + }, + "exports": { + ".": { + "types": "./dist/types/index.d.ts", + "require": "./dist/index.cjs", + "import": "./dist/index.mjs" + }, + "./vite": { + "types": "./dist/types/vite.d.ts", + "require": "./dist/vite.cjs", + "import": "./dist/vite.mjs" + }, + "./rollup": { + "types": "./dist/types/rollup.d.ts", + "require": "./dist/rollup.cjs", + "import": "./dist/rollup.mjs" + }, + "./svelte": { + "types": "./dist/types/svelte-elements.d.ts" + }, + "./custom-elements.json": "./custom-elements.json", + "./web-types.json": "./src/generated/web-types.json" + }, + "peerDependencies": { + "@beamable/sdk": "1.0.0", + "svelte": ">=4.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + } + }, + "devDependencies": { + "@beamable/sdk": "1.0.0", + "svelte": "^5.0.0", + "tsdown": "^0.16.5", + "typescript": "^5.8.3" + } +} diff --git a/beam-portal-toolkit/pnpm-lock.yaml b/beam-portal-toolkit/pnpm-lock.yaml new file mode 100644 index 0000000000..a9c2ce5aab --- /dev/null +++ b/beam-portal-toolkit/pnpm-lock.yaml @@ -0,0 +1,880 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + beamable-sdk: + specifier: 0.6.0 + version: 0.6.0 + devDependencies: + svelte: + specifier: ^5.0.0 + version: 5.55.0 + tsdown: + specifier: ^0.16.5 + version: 0.16.8(typescript@5.9.3) + typescript: + specifier: ^5.8.3 + version: 5.9.3 + +packages: + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@emnapi/core@1.9.1': + resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} + + '@emnapi/runtime@1.9.1': + resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} + + '@emnapi/wasi-threads@1.2.0': + resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + + '@oxc-project/types@0.122.0': + resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} + + '@oxc-project/types@0.99.0': + resolution: {integrity: sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==} + + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + + '@rolldown/binding-android-arm64@1.0.0-beta.52': + resolution: {integrity: sha512-MBGIgysimZPqTDcLXI+i9VveijkP5C3EAncEogXhqfax6YXj1Tr2LY3DVuEOMIjWfMPMhtQSPup4fSTAmgjqIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-android-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-SJ+/g+xNnOh6NqYxD0V3uVN4W3VfnrGsC9/hoglicgTNfABFG9JjISvkkU0dNY84MNHLWyOgxP9v9Y9pX4S7+A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.52': + resolution: {integrity: sha512-MmKeoLnKu1d9j6r19K8B+prJnIZ7u+zQ+zGQ3YHXGnr41rzE3eqQLovlkvoZnRoxDGPA4ps0pGiwXy6YE3lJyg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-7WQgR8SfOPwmDZGFkThUvsmd/nwAWv91oCO4I5LS7RKrssPZmOt7jONN0cW17ydGC1n/+puol1IpoieKqQidmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.52': + resolution: {integrity: sha512-qpHedvQBmIjT8zdnjN3nWPR2qjQyJttbXniCEKKdHeAbZG9HyNPBUzQF7AZZGwmS9coQKL+hWg9FhWzh2dZ2IA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.11': + resolution: {integrity: sha512-39Ks6UvIHq4rEogIfQBoBRusj0Q0nPVWIvqmwBLaT6aqQGIakHdESBVOPRRLacy4WwUPIx4ZKzfZ9PMW+IeyUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.52': + resolution: {integrity: sha512-dDp7WbPapj/NVW0LSiH/CLwMhmLwwKb3R7mh2kWX+QW85X1DGVnIEyKh9PmNJjB/+suG1dJygdtdNPVXK1hylg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.11': + resolution: {integrity: sha512-jfsm0ZHfhiqrvWjJAmzsqiIFPz5e7mAoCOPBNTcNgkiid/LaFKiq92+0ojH+nmJmKYkre4t71BWXUZDNp7vsag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.52': + resolution: {integrity: sha512-9e4l6vy5qNSliDPqNfR6CkBOAx6PH7iDV4OJiEJzajajGrVy8gc/IKKJUsoE52G8ud8MX6r3PMl97NfwgOzB7g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11': + resolution: {integrity: sha512-zjQaUtSyq1nVe3nxmlSCuR96T1LPlpvmJ0SZy0WJFEsV4kFbXcq2u68L4E6O0XeFj4aex9bEauqjW8UQBeAvfQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.52': + resolution: {integrity: sha512-V48oDR84feRU2KRuzpALp594Uqlx27+zFsT6+BgTcXOtu7dWy350J1G28ydoCwKB+oxwsRPx2e7aeQnmd3YJbQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-WMW1yE6IOnehTcFE9eipFkm3XN63zypWlrJQ2iF7NrQ9b2LDRjumFoOGJE8RJJTJCTBAdmLMnJ8uVitACUUo1Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.52': + resolution: {integrity: sha512-ENLmSQCWqSA/+YN45V2FqTIemg7QspaiTjlm327eUAMeOLdqmSOVVyrQexJGNTQ5M8sDYCgVAig2Kk01Ggmqaw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.11': + resolution: {integrity: sha512-jfndI9tsfm4APzjNt6QdBkYwre5lRPUgHeDHoI7ydKUuJvz3lZeCfMsI56BZj+7BYqiKsJm7cfd/6KYV7ubrBg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-ZlFgw46NOAGMgcdvdYwAGu2Q+SLFA9LzbJLW+iyMOJyhj5wk6P3KEE9Gct4xWwSzFoPI7JCdYmYMzVtlgQ+zfw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-hIOYmuT6ofM4K04XAZd3OzMySEO4K0/nc9+jmNcxNAxRi6c5UWpqfw3KMFV4MVFWL+jQsSh+bGw2VqmaPMTLyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.52': + resolution: {integrity: sha512-klahlb2EIFltSUubn/VLjuc3qxp1E7th8ukayPfdkcKvvYcQ5rJztgx8JsJSuAKVzKtNTqUGOhy4On71BuyV8g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-qXBQQO9OvkjjQPLdUVr7Nr2t3QTZI7s4KZtfw7HzBgjbmAPSFwSv4rmET9lLSgq3rH/ndA3ngv3Qb8l2njoPNA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.52': + resolution: {integrity: sha512-UuA+JqQIgqtkgGN2c/AQ5wi8M6mJHrahz/wciENPTeI6zEIbbLGoth5XN+sQe2pJDejEVofN9aOAp0kaazwnVg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.11': + resolution: {integrity: sha512-/tpFfoSTzUkH9LPY+cYbqZBDyyX62w5fICq9qzsHLL8uTI6BHip3Q9Uzft0wylk/i8OOwKik8OxW+QAhDmzwmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.52': + resolution: {integrity: sha512-1BNQW8u4ro8bsN1+tgKENJiqmvc+WfuaUhXzMImOVSMw28pkBKdfZtX2qJPADV3terx+vNJtlsgSGeb3+W6Jiw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-mcp3Rio2w72IvdZG0oQ4bM2c2oumtwHfUfKncUM6zGgz0KgPz4YmDPQfnXEiY5t3+KD/i8HG2rOB/LxdmieK2g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.52': + resolution: {integrity: sha512-K/p7clhCqJOQpXGykrFaBX2Dp9AUVIDHGc+PtFGBwg7V+mvBTv/tsm3LC3aUmH02H2y3gz4y+nUTQ0MLpofEEg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.11': + resolution: {integrity: sha512-LXk5Hii1Ph9asuGRjBuz8TUxdc1lWzB7nyfdoRgI0WGPZKmCxvlKk8KfYysqtr4MfGElu/f/pEQRh8fcEgkrWw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52': + resolution: {integrity: sha512-a4EkXBtnYYsKipjS7QOhEBM4bU5IlR9N1hU+JcVEVeuTiaslIyhWVKsvf7K2YkQHyVAJ+7/A9BtrGqORFcTgng==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11': + resolution: {integrity: sha512-dDwf5otnx0XgRY1yqxOC4ITizcdzS/8cQ3goOWv3jFAo4F+xQYni+hnMuO6+LssHHdJW7+OCVL3CoU4ycnh35Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.52': + resolution: {integrity: sha512-5ZXcYyd4GxPA6QfbGrNcQjmjbuLGvfz6728pZMsQvGHI+06LT06M6TPtXvFvLgXtexc+OqvFe1yAIXJU1gob/w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.52': + resolution: {integrity: sha512-tzpnRQXJrSzb8Z9sm97UD3cY0toKOImx+xRKsDLX4zHaAlRXWh7jbaKBePJXEN7gNw7Nm03PBNwphdtA8KSUYQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.11': + resolution: {integrity: sha512-LN4/skhSggybX71ews7dAj6r2geaMJfm3kMbK2KhFMg9B10AZXnKoLCVVgzhMHL0S+aKtr4p8QbAW8k+w95bAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.52': + resolution: {integrity: sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==} + + '@rolldown/pluginutils@1.0.0-rc.11': + resolution: {integrity: sha512-xQO9vbwBecJRv9EUcQ/y0dzSTJgA7Q6UVN7xp6B81+tBGSLVAK03yJ9NkJaUA7JFD91kbjxRSC/mDnmvXzbHoQ==} + + '@sveltejs/acorn-typescript@1.0.9': + resolution: {integrity: sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==} + peerDependencies: + acorn: ^8.9.0 + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@typescript-eslint/types@8.57.2': + resolution: {integrity: sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + + aria-query@5.3.1: + resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} + engines: {node: '>= 0.4'} + + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + beamable-sdk@0.6.0: + resolution: {integrity: sha512-hWer2//p7XCw01uMg3bebjd7155dcM4bRkbwt54sshMq42QTNVz5PD1jOrxYJKRScmZRzC6c0yp3EQpCsncUnw==} + engines: {node: '>=22.14.0'} + + birpc@4.0.0: + resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + devalue@5.6.4: + resolution: {integrity: sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==} + + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + + dts-resolver@2.1.3: + resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} + engines: {node: '>=20.19.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + esrap@2.2.4: + resolution: {integrity: sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + get-tsconfig@4.13.7: + resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + rolldown-plugin-dts@0.18.4: + resolution: {integrity: sha512-7UpdiICFd/BhdjKtDPeakCFRk6pbkTGFe0Z6u01egt4c8aoO+JoPGF1Smc+JRuCH2s5j5hBdteBi0e10G0xQdQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@ts-macro/tsc': ^0.3.6 + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-beta.51 + typescript: ^5.0.0 + vue-tsc: ~3.1.0 + peerDependenciesMeta: + '@ts-macro/tsc': + optional: true + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-beta.52: + resolution: {integrity: sha512-Hbnpljue+JhMJrlOjQ1ixp9me7sUec7OjFvS+A1Qm8k8Xyxmw3ZhxFu7LlSXW1s9AX3POE9W9o2oqCEeR5uDmg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rolldown@1.0.0-rc.11: + resolution: {integrity: sha512-NRjoKMusSjfRbSYiH3VSumlkgFe7kYAa3pzVOsVYVFY3zb5d7nS+a3KGQ7hJKXuYWbzJKPVQ9Wxq2UvyK+ENpw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + svelte@5.55.0: + resolution: {integrity: sha512-SThllKq6TRMBwPtat7ASnm/9CDXnIhBR0NPGw0ujn2DVYx9rVwsPZxDaDQcYGdUz/3BYVsCzdq7pZarRQoGvtw==} + engines: {node: '>=18'} + + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + tsdown@0.16.8: + resolution: {integrity: sha512-6ANw9mgU9kk7SvTBKvpDu/DVJeAFECiLUSeL5M7f5Nm5H97E7ybxmXT4PQ23FySYn32y6OzjoAH/lsWCbGzfLA==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@vitejs/devtools': ^0.0.0-alpha.18 + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@vitejs/devtools': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + unrun@0.2.33: + resolution: {integrity: sha512-urXTjZHOHS6lMnatQerLcBpcTsaKZYGuu9aSZ+HlNfCApkiINRbj7YecC9h9hdZroMT4WQ4KVyzHfBqHKuFX9Q==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + +snapshots: + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@emnapi/core@1.9.1': + dependencies: + '@emnapi/wasi-threads': 1.2.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.9.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@1.1.1': + dependencies: + '@emnapi/core': 1.9.1 + '@emnapi/runtime': 1.9.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@oxc-project/types@0.122.0': {} + + '@oxc-project/types@0.99.0': {} + + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + + '@rolldown/binding-android-arm64@1.0.0-beta.52': + optional: true + + '@rolldown/binding-android-arm64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.52': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.52': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.52': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.52': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.52': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.52': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.52': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.11': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.52': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.11': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.52': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.11': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.52': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.11': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11': + optional: true + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.52': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.52': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.11': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.52': {} + + '@rolldown/pluginutils@1.0.0-rc.11': {} + + '@sveltejs/acorn-typescript@1.0.9(acorn@8.16.0)': + dependencies: + acorn: 8.16.0 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/estree@1.0.8': {} + + '@types/trusted-types@2.0.7': {} + + '@typescript-eslint/types@8.57.2': {} + + acorn@8.16.0: {} + + ansis@4.2.0: {} + + aria-query@5.3.1: {} + + ast-kit@2.2.0: + dependencies: + '@babel/parser': 7.29.2 + pathe: 2.0.3 + + axobject-query@4.1.0: {} + + beamable-sdk@0.6.0: {} + + birpc@4.0.0: {} + + cac@6.7.14: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + clsx@2.1.1: {} + + devalue@5.6.4: {} + + diff@8.0.4: {} + + dts-resolver@2.1.3: {} + + empathic@2.0.0: {} + + esm-env@1.2.2: {} + + esrap@2.2.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@typescript-eslint/types': 8.57.2 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + get-tsconfig@4.13.7: + dependencies: + resolve-pkg-maps: 1.0.0 + + hookable@5.5.3: {} + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + jsesc@3.1.0: {} + + locate-character@3.0.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + obug@2.1.1: {} + + pathe@2.0.3: {} + + picomatch@4.0.4: {} + + quansync@1.0.0: {} + + readdirp@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + rolldown-plugin-dts@0.18.4(rolldown@1.0.0-beta.52)(typescript@5.9.3): + dependencies: + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + ast-kit: 2.2.0 + birpc: 4.0.0 + dts-resolver: 2.1.3 + get-tsconfig: 4.13.7 + magic-string: 0.30.21 + obug: 2.1.1 + rolldown: 1.0.0-beta.52 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - oxc-resolver + + rolldown@1.0.0-beta.52: + dependencies: + '@oxc-project/types': 0.99.0 + '@rolldown/pluginutils': 1.0.0-beta.52 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.52 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.52 + '@rolldown/binding-darwin-x64': 1.0.0-beta.52 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.52 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.52 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.52 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.52 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.52 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.52 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.52 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.52 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.52 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.52 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.52 + + rolldown@1.0.0-rc.11: + dependencies: + '@oxc-project/types': 0.122.0 + '@rolldown/pluginutils': 1.0.0-rc.11 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.11 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.11 + '@rolldown/binding-darwin-x64': 1.0.0-rc.11 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.11 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.11 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.11 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.11 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.11 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.11 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.11 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.11 + + semver@7.7.4: {} + + svelte@5.55.0: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) + '@types/estree': 1.0.8 + '@types/trusted-types': 2.0.7 + acorn: 8.16.0 + aria-query: 5.3.1 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.6.4 + esm-env: 1.2.2 + esrap: 2.2.4 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + + tinyexec@1.0.4: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tree-kill@1.2.2: {} + + tsdown@0.16.8(typescript@5.9.3): + dependencies: + ansis: 4.2.0 + cac: 6.7.14 + chokidar: 5.0.0 + diff: 8.0.4 + empathic: 2.0.0 + hookable: 5.5.3 + obug: 2.1.1 + rolldown: 1.0.0-beta.52 + rolldown-plugin-dts: 0.18.4(rolldown@1.0.0-beta.52)(typescript@5.9.3) + semver: 7.7.4 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + unconfig-core: 7.5.0 + unrun: 0.2.33 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@ts-macro/tsc' + - '@typescript/native-preview' + - oxc-resolver + - synckit + - vue-tsc + + tslib@2.8.1: + optional: true + + typescript@5.9.3: {} + + unconfig-core@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + + unrun@0.2.33: + dependencies: + rolldown: 1.0.0-rc.11 + + zimmerframe@1.1.4: {} diff --git a/beam-portal-toolkit/scripts/sync-components.mjs b/beam-portal-toolkit/scripts/sync-components.mjs new file mode 100644 index 0000000000..43e13a1bb3 --- /dev/null +++ b/beam-portal-toolkit/scripts/sync-components.mjs @@ -0,0 +1,241 @@ +#!/usr/bin/env node +/** + * sync-components.mjs + * + * Regenerates from the CEM source: + * - web-types.json (JetBrains IDE autocomplete) + * - src/globals.ts (TypeScript HTMLElementTagNameMap augmentations) + * - src/svelte-elements.ts (Svelte SvelteHTMLElements augmentations) + * + * By default also copies beam-components.json from the Portal repo into + * custom-elements.json first. Pass --no-copy to skip that step and use the + * existing custom-elements.json instead. + * + * Usage: + * pnpm sync-components # copy from Portal, then regenerate + * pnpm sync-components --no-copy # regenerate from existing custom-elements.json + * + * When copying, the Portal repo is expected to be a sibling of BeamableProduct: + * ~/Documents/Github/Portal/ + * + * Override via env var if it lives elsewhere: + * PORTAL_REPO_PATH=/path/to/Portal pnpm sync-components + */ + +import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = resolve(__dirname, '..'); + +const noCopy = process.argv.includes('--no-copy'); + +// --------------------------------------------------------------------------- +// Paths +// --------------------------------------------------------------------------- + +const portalRepo = + process.env.PORTAL_REPO_PATH ?? resolve(root, '../../Portal'); +const cemSource = resolve(portalRepo, 'static/beam-components.json'); +const cemDest = resolve(root, 'custom-elements.json'); +const webTypesDest = resolve(root, 'src/generated/web-types.json'); +const globalsDest = resolve(root, 'src/generated/globals.ts'); +const svelteElementsDest = resolve(root, 'src/generated/svelte-elements.ts'); + +// --------------------------------------------------------------------------- +// Step 1: Read (and optionally copy) CEM +// --------------------------------------------------------------------------- + +let cem; + +if (noCopy) { + if (!existsSync(cemDest)) { + console.error(`\nERROR: custom-elements.json not found at:\n ${cemDest}\n`); + console.error('Run without --no-copy to fetch it from Portal first.'); + process.exit(1); + } + cem = JSON.parse(readFileSync(cemDest, 'utf8')); + console.log(`✓ Using existing custom-elements.json (--no-copy)`); +} else { + if (!existsSync(cemSource)) { + console.error(`\nERROR: CEM file not found at:\n ${cemSource}\n`); + console.error( + 'Set the PORTAL_REPO_PATH env var to point to your Portal repo root,\n' + + 'or pass --no-copy to regenerate from the existing custom-elements.json.', + ); + process.exit(1); + } + cem = JSON.parse(readFileSync(cemSource, 'utf8')); + writeFileSync(cemDest, JSON.stringify(cem, null, 2) + '\n'); + console.log(`✓ Copied CEM → custom-elements.json`); +} + +// --------------------------------------------------------------------------- +// Step 2: Collect declarations +// --------------------------------------------------------------------------- + +/** @type {Array<{kind: string, tagName: string, name: string, description?: string, attributes?: Array<{name: string, description?: string, type?: {text: string}}>, members?: Array<{kind: string, name: string, type?: {text: string}}>}>} */ +const declarations = cem.modules.flatMap((m) => + (m.declarations ?? []).filter( + (d) => d.kind === 'custom-element' && d.tagName, + ), +); + +if (declarations.length === 0) { + console.warn('⚠ No custom-element declarations found in CEM. Aborting.'); + process.exit(0); +} + +// --------------------------------------------------------------------------- +// Step 3: Generate web-types.json +// --------------------------------------------------------------------------- + +const pkgVersion = JSON.parse( + readFileSync(resolve(root, 'package.json'), 'utf8'), +).version; + +const webTypes = { + $schema: + 'https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json', + name: '@beamable/portal-toolkit', + version: pkgVersion, + 'js-types-syntax': 'typescript', + 'description-markup': 'markdown', + contributions: { + html: { + elements: declarations.map((decl) => ({ + name: decl.tagName, + description: decl.description ?? '', + attributes: (decl.attributes ?? []).map((attr) => ({ + name: attr.name, + description: attr.description ?? '', + value: { + type: attr.type?.text ?? 'any', + }, + })), + })), + }, + }, +}; + +writeFileSync(webTypesDest, JSON.stringify(webTypes, null, 2) + '\n'); +console.log( + `✓ Generated → src/generated/web-types.json (${declarations.length} components)`, +); + +// --------------------------------------------------------------------------- +// Step 4: Generate src/globals.ts +// --------------------------------------------------------------------------- + +/** + * Convert a CEM type text string to a TypeScript type string. + * CEM type.text is usually already valid TS, but a few common names differ. + */ +function toTsType(typeText) { + if (!typeText) return 'unknown'; + const normalized = typeText.trim(); + const overrides = { + array: 'unknown[]', + Array: 'unknown[]', + object: 'Record', + Object: 'Record', + }; + return overrides[normalized] ?? normalized; +} + +/** 'beam-some-thing' → 'BeamSomeThing' */ +function toPascalCase(tagName) { + return tagName + .split('-') + .map((s) => s.charAt(0).toUpperCase() + s.slice(1)) + .join(''); +} + +/** 'beam-btn' → 'BeamBtnElement' */ +function toIfaceName(tagName) { + return `${toPascalCase(tagName)}Element`; +} + +// HTMLElementTagNameMap entries +const tagMapLines = declarations + .map((d) => ` '${d.tagName}': ${toIfaceName(d.tagName)};`) + .join('\n'); + +// Per-element interface blocks (use members for JS property access) +const ifaceBlocks = declarations.map((decl) => { + const members = (decl.members ?? []) + .filter((m) => m.kind === 'field' && m.name) + .map((m) => ` ${m.name}?: ${toTsType(m.type?.text)};`) + .join('\n'); + + const body = members || ' // No public properties defined in CEM.'; + return ` interface ${toIfaceName(decl.tagName)} extends HTMLElement {\n${body}\n }`; +}); + +const globalsTs = `// AUTO-GENERATED — do not edit manually. +// Run \`pnpm sync-components\` to regenerate from Portal's beam-components.json. + +export {}; + +declare global { + // --------------------------------------------------------------------------- + // Tag → element type mapping. + // Gives TypeScript callers correct types for: + // document.querySelector('beam-btn') → BeamBtnElement + // document.createElement('beam-btn') → BeamBtnElement + // --------------------------------------------------------------------------- + interface HTMLElementTagNameMap { +${tagMapLines} + } + + // --------------------------------------------------------------------------- + // Per-element interfaces + // --------------------------------------------------------------------------- +${ifaceBlocks.join('\n\n')} +} +`; + +mkdirSync(resolve(root, 'src/generated'), { recursive: true }); +writeFileSync(globalsDest, globalsTs); +console.log(`✓ Generated → src/generated/globals.ts`); + +// --------------------------------------------------------------------------- +// Step 5: Generate src/generated/svelte-elements.ts +// --------------------------------------------------------------------------- + +// Use attributes (kebab-case) for Svelte since templates use HTML attribute names. +const svelteElementEntries = declarations.map((decl) => { + const attrs = (decl.attributes ?? []) + .map((a) => { + const key = a.name.includes('-') ? `'${a.name}'` : a.name; + return ` ${key}?: ${toTsType(a.type?.text)};`; + }) + .join('\n'); + + const body = attrs || ' // No attributes defined in CEM.'; + return ` '${decl.tagName}': import('svelte/elements').HTMLAttributes & {\n${body}\n };`; +}); + +const svelteElementsTs = `// AUTO-GENERATED — do not edit manually. +// Run \`pnpm sync-components\` to regenerate from Portal's beam-components.json. +// +// Augments Svelte's element type map so .svelte templates get autocomplete +// for Beamable web components. +// +// Add one line to your project's app.d.ts (or any .d.ts file): +// /// + +declare module 'svelte/elements' { + interface SvelteHTMLElements { +${svelteElementEntries.join('\n\n')} + } +} + +export {}; +`; + +writeFileSync(svelteElementsDest, svelteElementsTs); +console.log(`✓ Generated → src/generated/svelte-elements.ts`); + +console.log(`\nDone. Run \`pnpm build\` to compile the updated types.\n`); diff --git a/beam-portal-toolkit/src/generated/globals.ts b/beam-portal-toolkit/src/generated/globals.ts new file mode 100644 index 0000000000..1683366fd5 --- /dev/null +++ b/beam-portal-toolkit/src/generated/globals.ts @@ -0,0 +1,159 @@ +// AUTO-GENERATED — do not edit manually. +// Run `pnpm sync-components` to regenerate from Portal's beam-components.json. + +export {}; + +declare global { + // --------------------------------------------------------------------------- + // Tag → element type mapping. + // Gives TypeScript callers correct types for: + // document.querySelector('beam-btn') → BeamBtnElement + // document.createElement('beam-btn') → BeamBtnElement + // --------------------------------------------------------------------------- + interface HTMLElementTagNameMap { + 'beam-btn': BeamBtnElement; + 'beam-icon': BeamIconElement; + 'beam-chip': BeamChipElement; + 'beam-alert': BeamAlertElement; + 'beam-card': BeamCardElement; + 'beam-card-title': BeamCardTitleElement; + 'beam-card-subtitle': BeamCardSubtitleElement; + 'beam-card-text': BeamCardTextElement; + 'beam-card-actions': BeamCardActionsElement; + 'beam-data-table': BeamDataTableElement; + } + + // --------------------------------------------------------------------------- + // Per-element interfaces + // --------------------------------------------------------------------------- + interface BeamBtnElement extends HTMLElement { + color?: string; + outlined?: boolean; + text?: boolean; + block?: boolean; + disabled?: boolean; + small?: boolean; + large?: boolean; + xSmall?: boolean; + xLarge?: boolean; + icon?: boolean; + fab?: boolean; + tile?: boolean; + rounded?: boolean; + depressed?: boolean; + dark?: boolean; + light?: boolean; + loading?: boolean; + href?: string; + target?: string; + type?: string; + elevation?: string; + } + + interface BeamIconElement extends HTMLElement { + icon?: string; + color?: string; + small?: boolean; + large?: boolean; + xSmall?: boolean; + xLarge?: boolean; + dense?: boolean; + disabled?: boolean; + dark?: boolean; + light?: boolean; + left?: boolean; + right?: boolean; + } + + interface BeamChipElement extends HTMLElement { + color?: string; + outlined?: boolean; + small?: boolean; + large?: boolean; + xSmall?: boolean; + close?: boolean; + disabled?: boolean; + dark?: boolean; + light?: boolean; + label?: boolean; + pill?: boolean; + } + + interface BeamAlertElement extends HTMLElement { + color?: string; + type?: string; + outlined?: boolean; + text?: boolean; + dense?: boolean; + dismissible?: boolean; + icon?: string; + border?: string; + elevation?: string; + dark?: boolean; + light?: boolean; + prominent?: boolean; + tile?: boolean; + } + + interface BeamCardElement extends HTMLElement { + elevation?: string; + } + + interface BeamCardTitleElement extends HTMLElement { + // No public properties defined in CEM. + } + + interface BeamCardSubtitleElement extends HTMLElement { + // No public properties defined in CEM. + } + + interface BeamCardTextElement extends HTMLElement { + // No public properties defined in CEM. + } + + interface BeamCardActionsElement extends HTMLElement { + // No public properties defined in CEM. + } + + interface BeamDataTableElement extends HTMLElement { + headers?: unknown[]; + items?: unknown[]; + itemsPerPage?: string; + loading?: boolean; + search?: string; + sortBy?: string; + sortDesc?: string; + multiSort?: boolean; + mustSort?: boolean; + showSelect?: boolean; + singleSelect?: boolean; + value?: string; + dense?: boolean; + fixedHeader?: boolean; + height?: string; + hideDefaultHeader?: boolean; + hideDefaultFooter?: boolean; + noDataText?: string; + noResultsText?: string; + dark?: boolean; + light?: boolean; + itemKey?: string; + itemClass?: string; + page?: string; + serverItemsLength?: string; + disablePagination?: boolean; + disableSort?: boolean; + showExpand?: boolean; + expanded?: string; + groupBy?: string; + groupDesc?: string; + showGroupBy?: boolean; + mobileBreakpoint?: string; + loaderHeight?: string; + loadingText?: string; + footerProps?: string; + headerProps?: string; + calculateWidths?: boolean; + caption?: string; + } +} diff --git a/beam-portal-toolkit/src/generated/svelte-elements.ts b/beam-portal-toolkit/src/generated/svelte-elements.ts new file mode 100644 index 0000000000..b7dec9c5f7 --- /dev/null +++ b/beam-portal-toolkit/src/generated/svelte-elements.ts @@ -0,0 +1,145 @@ +// AUTO-GENERATED — do not edit manually. +// Run `pnpm sync-components` to regenerate from Portal's beam-components.json. +// +// Augments Svelte's element type map so .svelte templates get autocomplete +// for Beamable web components. +// +// Add one line to your project's app.d.ts (or any .d.ts file): +// /// + +declare module 'svelte/elements' { + interface SvelteHTMLElements { + 'beam-btn': import('svelte/elements').HTMLAttributes & { + color?: string; + outlined?: boolean; + text?: boolean; + block?: boolean; + disabled?: boolean; + small?: boolean; + large?: boolean; + 'x-small'?: boolean; + 'x-large'?: boolean; + icon?: boolean; + fab?: boolean; + tile?: boolean; + rounded?: boolean; + depressed?: boolean; + dark?: boolean; + light?: boolean; + loading?: boolean; + href?: string; + target?: string; + type?: string; + elevation?: string; + }; + + 'beam-icon': import('svelte/elements').HTMLAttributes & { + icon?: string; + color?: string; + small?: boolean; + large?: boolean; + 'x-small'?: boolean; + 'x-large'?: boolean; + dense?: boolean; + disabled?: boolean; + dark?: boolean; + light?: boolean; + left?: boolean; + right?: boolean; + }; + + 'beam-chip': import('svelte/elements').HTMLAttributes & { + color?: string; + outlined?: boolean; + small?: boolean; + large?: boolean; + 'x-small'?: boolean; + close?: boolean; + disabled?: boolean; + dark?: boolean; + light?: boolean; + label?: boolean; + pill?: boolean; + }; + + 'beam-alert': import('svelte/elements').HTMLAttributes & { + color?: string; + type?: string; + outlined?: boolean; + text?: boolean; + dense?: boolean; + dismissible?: boolean; + icon?: string; + border?: string; + elevation?: string; + dark?: boolean; + light?: boolean; + prominent?: boolean; + tile?: boolean; + }; + + 'beam-card': import('svelte/elements').HTMLAttributes & { + elevation?: string; + }; + + 'beam-card-title': import('svelte/elements').HTMLAttributes & { + // No attributes defined in CEM. + }; + + 'beam-card-subtitle': import('svelte/elements').HTMLAttributes & { + // No attributes defined in CEM. + }; + + 'beam-card-text': import('svelte/elements').HTMLAttributes & { + // No attributes defined in CEM. + }; + + 'beam-card-actions': import('svelte/elements').HTMLAttributes & { + // No attributes defined in CEM. + }; + + 'beam-data-table': import('svelte/elements').HTMLAttributes & { + headers?: unknown[]; + items?: unknown[]; + 'items-per-page'?: string; + loading?: boolean; + search?: string; + 'sort-by'?: string; + 'sort-desc'?: string; + 'multi-sort'?: boolean; + 'must-sort'?: boolean; + 'show-select'?: boolean; + 'single-select'?: boolean; + value?: string; + dense?: boolean; + 'fixed-header'?: boolean; + height?: string; + 'hide-default-header'?: boolean; + 'hide-default-footer'?: boolean; + 'no-data-text'?: string; + 'no-results-text'?: string; + dark?: boolean; + light?: boolean; + 'item-key'?: string; + 'item-class'?: string; + page?: string; + 'server-items-length'?: string; + 'disable-pagination'?: boolean; + 'disable-sort'?: boolean; + 'show-expand'?: boolean; + expanded?: string; + 'group-by'?: string; + 'group-desc'?: string; + 'show-group-by'?: boolean; + 'mobile-breakpoint'?: string; + 'loader-height'?: string; + 'loading-text'?: string; + 'footer-props'?: string; + 'header-props'?: string; + 'calculate-widths'?: boolean; + caption?: string; + }; + } +} + +export {}; diff --git a/beam-portal-toolkit/src/generated/web-types.json b/beam-portal-toolkit/src/generated/web-types.json new file mode 100644 index 0000000000..6a95c429a2 --- /dev/null +++ b/beam-portal-toolkit/src/generated/web-types.json @@ -0,0 +1,748 @@ +{ + "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json", + "name": "@beamable/portal-toolkit", + "version": "0.1.2", + "js-types-syntax": "typescript", + "description-markup": "markdown", + "contributions": { + "html": { + "elements": [ + { + "name": "beam-btn", + "description": "A Material Design button. Supports outlined, text, icon, fab, and loading variants.", + "attributes": [ + { + "name": "color", + "description": "Fill or text color. Accepts a CSS color or theme color name (e.g. `primary`, `secondary`, `error`).", + "value": { + "type": "string" + } + }, + { + "name": "outlined", + "description": "Renders with a border and transparent background.", + "value": { + "type": "boolean" + } + }, + { + "name": "text", + "description": "Renders as a flat text button with no background or border.", + "value": { + "type": "boolean" + } + }, + { + "name": "block", + "description": "Expands the button to fill its container's full width.", + "value": { + "type": "boolean" + } + }, + { + "name": "disabled", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "small", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "large", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "x-small", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "x-large", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "icon", + "description": "Renders as a square icon button sized to fit a single icon.", + "value": { + "type": "boolean" + } + }, + { + "name": "fab", + "description": "Renders as a circular floating action button.", + "value": { + "type": "boolean" + } + }, + { + "name": "tile", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "rounded", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "depressed", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "loading", + "description": "Shows a loading spinner and disables the button.", + "value": { + "type": "boolean" + } + }, + { + "name": "href", + "description": "Renders the button as an anchor tag pointing to this URL.", + "value": { + "type": "string" + } + }, + { + "name": "target", + "description": "The `target` attribute forwarded to the anchor tag when `href` is set.", + "value": { + "type": "string" + } + }, + { + "name": "type", + "description": "The HTML button `type` attribute: `button`, `submit`, or `reset`.", + "value": { + "type": "string" + } + }, + { + "name": "elevation", + "description": "", + "value": { + "type": "string" + } + } + ] + }, + { + "name": "beam-icon", + "description": "Renders a Material Design icon by name. Pass the icon name via the `icon` prop or as default slot content.", + "attributes": [ + { + "name": "icon", + "description": "The Material Design icon name (e.g. `mdi-home`). Can also be passed as slot content.", + "value": { + "type": "string" + } + }, + { + "name": "color", + "description": "Icon color. Accepts a CSS color or theme color name (e.g. `primary`, `error`).", + "value": { + "type": "string" + } + }, + { + "name": "small", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "large", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "x-small", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "x-large", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dense", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "disabled", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "left", + "description": "Adds right margin — use when the icon precedes inline text.", + "value": { + "type": "boolean" + } + }, + { + "name": "right", + "description": "Adds left margin — use when the icon follows inline text.", + "value": { + "type": "boolean" + } + } + ] + }, + { + "name": "beam-chip", + "description": "A small label element used for tags, filters, or status indicators. Supports closeable, outlined, and pill variants.", + "attributes": [ + { + "name": "color", + "description": "Fill color. Accepts a CSS color or theme color name (e.g. `primary`, `error`).", + "value": { + "type": "string" + } + }, + { + "name": "outlined", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "small", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "large", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "x-small", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "close", + "description": "Shows a dismiss icon on the chip. Listen for the `click:close` event to handle removal.", + "value": { + "type": "boolean" + } + }, + { + "name": "disabled", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "label", + "description": "Renders as a square chip rather than rounded.", + "value": { + "type": "boolean" + } + }, + { + "name": "pill", + "description": "Renders with fully rounded (pill-shaped) ends.", + "value": { + "type": "boolean" + } + } + ] + }, + { + "name": "beam-alert", + "description": "Displays a contextual message to the user. Use the `type` prop for semantic variants: `success`, `info`, `warning`, or `error`.", + "attributes": [ + { + "name": "color", + "description": "Fill color. Overrides the color implied by `type`.", + "value": { + "type": "string" + } + }, + { + "name": "type", + "description": "Semantic variant: `success`, `info`, `warning`, or `error`. Sets icon and color automatically.", + "value": { + "type": "string" + } + }, + { + "name": "outlined", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "text", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dense", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dismissible", + "description": "Shows a close button. Listen for the `input` event (emits `false`) to handle dismissal.", + "value": { + "type": "boolean" + } + }, + { + "name": "icon", + "description": "Overrides the default icon for the current `type`. Pass `false` to remove the icon.", + "value": { + "type": "string" + } + }, + { + "name": "border", + "description": "Adds a colored border on one side: `top`, `right`, `bottom`, or `left`.", + "value": { + "type": "string" + } + }, + { + "name": "elevation", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "prominent", + "description": "Increases the alert height and renders the icon at a larger size.", + "value": { + "type": "boolean" + } + }, + { + "name": "tile", + "description": "", + "value": { + "type": "boolean" + } + } + ] + }, + { + "name": "beam-card", + "description": "A surface container with elevation and rounded corners for grouping related content.", + "attributes": [ + { + "name": "elevation", + "description": "Shadow depth (0–24). Maps to the `elevation-N` CSS class.", + "value": { + "type": "string" + } + } + ] + }, + { + "name": "beam-card-title", + "description": "The title region of a beam-card. Renders with card title typography.", + "attributes": [] + }, + { + "name": "beam-card-subtitle", + "description": "The subtitle region of a beam-card. Renders with card subtitle typography.", + "attributes": [] + }, + { + "name": "beam-card-text", + "description": "The body content region of a beam-card. Adds standard card padding.", + "attributes": [] + }, + { + "name": "beam-card-actions", + "description": "The actions region of a beam-card. Aligns action buttons at the bottom of the card.", + "attributes": [] + }, + { + "name": "beam-data-table", + "description": "A full-featured data table with sorting, pagination, filtering, and row selection.", + "attributes": [ + { + "name": "headers", + "description": "Column definitions. Each item requires a `text` (display label) and `value` (row data key).", + "value": { + "type": "array" + } + }, + { + "name": "items", + "description": "Array of row data objects. Each object's keys should match the `value` fields in `headers`.", + "value": { + "type": "array" + } + }, + { + "name": "items-per-page", + "description": "Number of rows shown per page. Set to `-1` to show all rows. Defaults to `10`.", + "value": { + "type": "string" + } + }, + { + "name": "loading", + "description": "Shows a loading bar above the table.", + "value": { + "type": "boolean" + } + }, + { + "name": "search", + "description": "Filters visible rows to those matching this string.", + "value": { + "type": "string" + } + }, + { + "name": "sort-by", + "description": "The column `value` key to sort by.", + "value": { + "type": "string" + } + }, + { + "name": "sort-desc", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "multi-sort", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "must-sort", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "show-select", + "description": "Adds a checkbox column for row selection. Use `value` to read or set the selected rows.", + "value": { + "type": "boolean" + } + }, + { + "name": "single-select", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "value", + "description": "The currently selected rows when `showSelect` is true.", + "value": { + "type": "string" + } + }, + { + "name": "dense", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "fixed-header", + "description": "Fixes the header row so only the body scrolls when `height` is set.", + "value": { + "type": "boolean" + } + }, + { + "name": "height", + "description": "Sets a fixed height on the table. Required for `fixedHeader` to take effect.", + "value": { + "type": "string" + } + }, + { + "name": "hide-default-header", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "hide-default-footer", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "no-data-text", + "description": "Message shown when `items` is empty.", + "value": { + "type": "string" + } + }, + { + "name": "no-results-text", + "description": "Message shown when `search` produces no matches.", + "value": { + "type": "string" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "item-key", + "description": "The row property used as a unique key. Defaults to `id`.", + "value": { + "type": "string" + } + }, + { + "name": "item-class", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "page", + "description": "The current page number (1-based).", + "value": { + "type": "string" + } + }, + { + "name": "server-items-length", + "description": "Total number of items on the server. Required for server-side pagination.", + "value": { + "type": "string" + } + }, + { + "name": "disable-pagination", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "disable-sort", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "show-expand", + "description": "Adds an expand toggle column. Use `expanded` to read or set expanded rows.", + "value": { + "type": "boolean" + } + }, + { + "name": "expanded", + "description": "Array of currently expanded row objects.", + "value": { + "type": "string" + } + }, + { + "name": "group-by", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "group-desc", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "show-group-by", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "mobile-breakpoint", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "loader-height", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "loading-text", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "footer-props", + "description": "Props forwarded to the footer pagination control.", + "value": { + "type": "string" + } + }, + { + "name": "header-props", + "description": "Props forwarded to the header row.", + "value": { + "type": "string" + } + }, + { + "name": "calculate-widths", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "caption", + "description": "", + "value": { + "type": "string" + } + } + ] + } + ] + } + } +} diff --git a/beam-portal-toolkit/src/index.ts b/beam-portal-toolkit/src/index.ts new file mode 100644 index 0000000000..3658f403eb --- /dev/null +++ b/beam-portal-toolkit/src/index.ts @@ -0,0 +1,11 @@ +// Utility functions for the Beamable portal extension system. +// Add utility exports here as the toolkit grows. + +// Pull in global HTMLElementTagNameMap augmentations so that any consumer +// who imports from this package automatically gets TypeScript types for all +// Beamable custom elements. The file itself is auto-generated — run +// `pnpm sync-components` to refresh it from Portal's beam-components.json. +import './generated/globals'; + +export * from '@beamable/sdk'; +export * from './portal'; diff --git a/beam-portal-toolkit/src/portal.ts b/beam-portal-toolkit/src/portal.ts new file mode 100644 index 0000000000..ae01344a25 --- /dev/null +++ b/beam-portal-toolkit/src/portal.ts @@ -0,0 +1,102 @@ +// Portal extension registration utilities. +// Import via: import { Portal } from '@beamable/portal-toolkit'; + +import { Beam, BeamBase } from "@beamable/sdk"; + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +/** + * Runtime context provided by the Beamable portal to every extension on mount. + */ +export interface ExtensionContext extends Map { + realm: string; + cid: string; + beam: Promise; +} + +/** + * Options passed to {@link Portal.registerExtension}. + */ +export interface RegisterExtensionOptions { + /** + * Unique name for the extension + */ + beamId: string; + + /** + * Called when the portal mounts this extension into the DOM. + * + * Render your UI into `container`. The portal guarantees that + * `container` is attached to the document before this callback fires. + * + * @returns some unique instance object for the service. The same instance will be given to the unmount call later. + * @param container - The `HTMLElement` allocated for this extension. + * @param context - Runtime context supplied by the portal. + */ + onMount: (container: HTMLElement, context: ExtensionContext) => unknown | Promise; + + /** + * Called when the portal is about to remove this extension from the DOM. + * + * Use this to tear down event listeners, timers, framework instances, etc. + * The portal waits for a returned `Promise` to settle before removing + * `container` from the DOM. + * @param instance - The instance object returned by the corresponding `onMount` call. + */ + onUnmount: (instance: unknown) => void | Promise; +} + + +// --------------------------------------------------------------------------- +// Implementation +// --------------------------------------------------------------------------- + +/** + * Registers an extension with the Beamable portal. + * + * @example + * ```ts + * import { Portal } from '@beamable/portal-toolkit'; + * + * Portal.registerExtension({ + * beamId: 'MyExtension', + * onMount(container, context) { + * container.innerHTML = `

Hello from ${context.realm}

`; + * }, + * onUnmount(instance) { + * // clean up + * }, + * }); + * ``` + */ +function registerExtension(options: RegisterExtensionOptions): void { + + (window as unknown as Record)[options.beamId] = { + mount: (targetElement: HTMLElement, context: ExtensionContext) => { + return options.onMount(targetElement, context); + }, + unmount: (instance: unknown) => { + return options.onUnmount(instance); + }, + }; + +} + +// --------------------------------------------------------------------------- +// Namespace export +// --------------------------------------------------------------------------- + +/** + * Top-level namespace for portal utilities. + * + * @example + * ```ts + * import { Portal } from '@beamable/portal-toolkit'; + * Portal.registerExtension({ ... }); + * ``` + */ +export const Portal = { + registerExtension, +} as const; diff --git a/beam-portal-toolkit/src/rollup.ts b/beam-portal-toolkit/src/rollup.ts new file mode 100644 index 0000000000..2745e58c62 --- /dev/null +++ b/beam-portal-toolkit/src/rollup.ts @@ -0,0 +1,45 @@ +/** + * Rollup config helpers for Beamable portal extensions. + * + * Provides pre-configured external/globals options so that `@beamable/sdk` + * and `@beamable/sdk/api` are excluded from the extension bundle and resolved + * to the versioned window globals that the Portal injects before running the + * extension script. + * + * Usage in rollup.config.js: + * + * import { portalExtensionRollupOptions } from '@beamable/portal-toolkit/rollup' + * + * export default { + * input: 'src/index.js', + * output: { + * file: 'dist/index.js', + * format: 'iife', + * name: 'MyExtensionName', // must match manifest.Name exactly + * ...portalExtensionRollupOptions.output, + * }, + * external: portalExtensionRollupOptions.external, + * } + */ + +import pkg from '../package.json' + +// Versioned global names the Portal registers on window before the extension +// script runs. Must match the `globalName` in the Portal's beam-sdk-registry. +const SDK_VERSION = pkg.peerDependencies['@beamable/sdk'] +const SDK_GLOBAL = `@beamable/sdk-${SDK_VERSION}` +const SDK_API_GLOBAL = `@beamable/sdk/api-${SDK_VERSION}` + +/** + * Spread `external` into the top-level rollup config and `output` into the + * output object. Both are read-only — do not mutate them. + */ +export const portalExtensionRollupOptions = { + external: ['@beamable/sdk', '@beamable/sdk/api'] as const, + output: { + globals: { + '@beamable/sdk': `window['${SDK_GLOBAL}']`, + '@beamable/sdk/api': `window['${SDK_API_GLOBAL}']`, + }, + }, +} as const diff --git a/beam-portal-toolkit/src/vite.ts b/beam-portal-toolkit/src/vite.ts new file mode 100644 index 0000000000..940724ee63 --- /dev/null +++ b/beam-portal-toolkit/src/vite.ts @@ -0,0 +1,56 @@ +/** + * Vite plugin for Beamable portal extensions. + * + * Configures the build so that `@beamable/sdk` and `@beamable/sdk/api` are + * treated as externals and resolved to the versioned window globals that the + * Portal injects before running the extension script. + * + * Usage in vite.config.js / vite.config.ts: + * + * import { portalExtensionPlugin } from '@beamable/portal-toolkit/vite' + * + * export default defineConfig({ + * plugins: [portalExtensionPlugin()], + * build: { + * lib: { + * entry: 'src/index.js', + * name: 'MyExtensionName', // must match manifest.Name exactly + * formats: ['iife'], + * fileName: () => 'index.js', + * }, + * }, + * }) + */ + +import pkg from '../package.json' + +// Versioned global names the Portal registers on window before the extension +// script runs. Must match the `globalName` in the Portal's beam-sdk-registry. +const SDK_VERSION = pkg.peerDependencies['@beamable/sdk'] +const SDK_GLOBAL = `@beamable/sdk-${SDK_VERSION}` +const SDK_API_GLOBAL = `@beamable/sdk/api-${SDK_VERSION}` + +/** + * Returns a Vite plugin that marks `@beamable/sdk` and `@beamable/sdk/api` + * as external and maps them to the Portal-provided window globals at runtime. + */ +export function portalExtensionPlugin() { + return { + name: 'beamable-portal-extension', + config() { + return { + build: { + rollupOptions: { + external: ['@beamable/sdk', '@beamable/sdk/api'], + output: { + globals: { + '@beamable/sdk': `window['${SDK_GLOBAL}']`, + '@beamable/sdk/api': `window['${SDK_API_GLOBAL}']`, + }, + }, + }, + }, + } + }, + } +} diff --git a/beam-portal-toolkit/tsconfig.json b/beam-portal-toolkit/tsconfig.json new file mode 100644 index 0000000000..21f48336d9 --- /dev/null +++ b/beam-portal-toolkit/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "declaration": true, + "stripInternal": true, + "outDir": "dist", + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "baseUrl": "." + }, + "include": ["src/**/*", "tsdown.config.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/beam-portal-toolkit/tsdown.config.ts b/beam-portal-toolkit/tsdown.config.ts new file mode 100644 index 0000000000..269614d774 --- /dev/null +++ b/beam-portal-toolkit/tsdown.config.ts @@ -0,0 +1,41 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig([ + // CJS + ESM build — runtime + build-tool entry points + { + entry: ['src/index.ts', 'src/vite.ts', 'src/rollup.ts'], + format: ['cjs', 'esm'], + outDir: 'dist', + clean: true, + dts: false, + sourcemap: false, + minify: true, + external: ['@beamable/sdk'], + }, + // Type declarations + { + entry: ['src/index.ts', 'src/vite.ts', 'src/rollup.ts'], + outDir: 'dist/types', + clean: false, + dts: { + emitDtsOnly: true, + }, + outExtensions: () => ({ + dts: '.d.ts', + }), + external: ['@beamable/sdk', 'svelte'], + }, + // Svelte element type augmentations + { + entry: ['src/generated/svelte-elements.ts'], + outDir: 'dist/types', + clean: false, + dts: { + emitDtsOnly: true, + }, + outExtensions: () => ({ + dts: '.d.ts', + }), + external: ['svelte'], + }, +]); diff --git a/build/bin/upload-web-sdk-sample-build.sh b/build/bin/upload-web-sdk-sample-build.sh index 8117fd2458..62b569d48b 100755 --- a/build/bin/upload-web-sdk-sample-build.sh +++ b/build/bin/upload-web-sdk-sample-build.sh @@ -8,7 +8,7 @@ workspace="${GITHUB_WORKSPACE:-.}" # Set Up Paths build_directory="$workspace/web-sdk-sample-build" -github_repo_url="https://$GITHUB_USERNAME:$GITHUB_PASSWORD@github.com/beamable/web-sdk-sample.git" +github_repo_url="https://x-access-token:$GIT_WEB_SDK_SAMPLE_PAT@github.com/beamable/web-sdk-sample.git" source_dist_folder="$workspace/$SAMPLE_DIR/dist" # Validate Source Files Exist diff --git a/cli/beamable.templates/templates/PortalExtensionApp/package.json b/cli/beamable.templates/templates/PortalExtensionApp/package.json index d2a7ebaa92..4c9d4d7787 100644 --- a/cli/beamable.templates/templates/PortalExtensionApp/package.json +++ b/cli/beamable.templates/templates/PortalExtensionApp/package.json @@ -22,9 +22,9 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^6.2.1", "svelte": "^5.43.5", - "vite": "^7.2.2" + "vite": "^7.2.2", + "@beamable/portal-toolkit": "0.1.2" }, "dependencies": { - "beamable-sdk": "^0.6.0" } } diff --git a/cli/beamable.templates/templates/PortalExtensionApp/src/App.svelte b/cli/beamable.templates/templates/PortalExtensionApp/src/App.svelte index 2a00f650d9..2c91f46418 100644 --- a/cli/beamable.templates/templates/PortalExtensionApp/src/App.svelte +++ b/cli/beamable.templates/templates/PortalExtensionApp/src/App.svelte @@ -1,10 +1,27 @@ - - \ No newline at end of file + + + New Extension + + +
+
+ Player ID {beam?.player.id} +
+ + Click + +
+
+
\ No newline at end of file diff --git a/cli/beamable.templates/templates/PortalExtensionApp/src/app.d.ts b/cli/beamable.templates/templates/PortalExtensionApp/src/app.d.ts new file mode 100644 index 0000000000..16e42c508a --- /dev/null +++ b/cli/beamable.templates/templates/PortalExtensionApp/src/app.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file diff --git a/cli/beamable.templates/templates/PortalExtensionApp/src/main.js b/cli/beamable.templates/templates/PortalExtensionApp/src/main.js index c7b044b636..bf0a748cad 100644 --- a/cli/beamable.templates/templates/PortalExtensionApp/src/main.js +++ b/cli/beamable.templates/templates/PortalExtensionApp/src/main.js @@ -1,17 +1,16 @@ import { mount, unmount } from 'svelte' import './app.css' import App from './App.svelte' +import { Portal } from '@beamable/portal-toolkit' -const APP_NAMESPACE = 'PortalExtensionApp'; - -window[APP_NAMESPACE] = { - mount: (targetElement, props) => { - return mount(App, { - target: targetElement, - props: props - }); - }, - unmount: (appInstance) => { - unmount(appInstance); - } -} +Portal.registerExtension({ + beamId: 'PortalExtensionApp', + onMount: (container, context) => { + return mount(App, { + target: container, + props: { context } }); + }, + onUnmount: instance => { + unmount(instance); + } +}) diff --git a/cli/beamable.templates/templates/PortalExtensionApp/vite.config.js b/cli/beamable.templates/templates/PortalExtensionApp/vite.config.js index d70528a600..853afa464e 100644 --- a/cli/beamable.templates/templates/PortalExtensionApp/vite.config.js +++ b/cli/beamable.templates/templates/PortalExtensionApp/vite.config.js @@ -1,8 +1,9 @@ import { defineConfig } from 'vite' import { svelte } from '@sveltejs/vite-plugin-svelte' +import { portalExtensionPlugin } from '@beamable/portal-toolkit/vite' export default defineConfig({ - plugins: [svelte()], + plugins: [svelte(), portalExtensionPlugin()], resolve: { dedupe: [] }, @@ -15,15 +16,10 @@ export default defineConfig({ formats: ['iife'], }, rollupOptions: { - external: ['beamable-sdk', 'beamable-sdk/api'], input: 'src/main.js', output: { format: 'iife', inlineDynamicImports: true, - globals: { - 'beamable-sdk': 'Beamable', - 'beamable-sdk/api': 'BeamableApi' - }, entryFileNames: 'main.js', assetFileNames: (assetInfo) => { if (assetInfo.name && assetInfo.name.endsWith('.css')) { diff --git a/cli/cli/Services/BeamoLocalSystem.cs b/cli/cli/Services/BeamoLocalSystem.cs index 5d4a51ce3a..a484431b38 100644 --- a/cli/cli/Services/BeamoLocalSystem.cs +++ b/cli/cli/Services/BeamoLocalSystem.cs @@ -823,9 +823,42 @@ public class PortalExtensionDef public string AbsolutePath; public string AbsolutePackageJsonPath => Path.Combine(AbsolutePath, "package.json"); - + public List MicroserviceDependencies => Properties.MicroserviceDependencies; public PortalExtensionPackageProperties Properties; + + private string ToolkitNodeModulesPackageJsonPath => + Path.Combine(AbsolutePath, "node_modules", "@beamable", "portal-toolkit", "package.json"); + + /// + /// Reads the @beamable/portal-toolkit version. If the devDependencies value is not a semver + /// (e.g. a file: reference), falls back to reading the installed toolkit's package.json version field. + /// + public string GetToolkitVersion() + { + try + { + var json = File.ReadAllText(AbsolutePackageJsonPath); + var root = Newtonsoft.Json.Linq.JObject.Parse(json); + var depVersion = (root["devDependencies"] as Newtonsoft.Json.Linq.JObject) + ?["@beamable/portal-toolkit"]?.ToString(); + + // If the version is a file: reference or other non-semver, resolve from the installed package + if (depVersion != null && !char.IsDigit(depVersion.TrimStart('^', '~')[0])) + { + var toolkitJson = File.ReadAllText(ToolkitNodeModulesPackageJsonPath); + var toolkitRoot = Newtonsoft.Json.Linq.JObject.Parse(toolkitJson); + return toolkitRoot.SelectToken("version")?.ToString() ?? depVersion; + } + + return depVersion; + } + catch + { + return null; + } + } + } /// diff --git a/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs index 73062401d7..b1a34175c3 100644 --- a/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs +++ b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs @@ -25,6 +25,7 @@ namespace cli.Services.PortalExtension; public class ExtensionBuildMetaData { public string Name; + public string ToolkitVersion; public PortalExtensionPackageProperties Properties; } @@ -58,10 +59,12 @@ public ExtensionBuildData RequestPortalExtensionData(string currentHash = "") public ExtensionBuildMetaData RequestMetaData() { var observer = Provider.GetService(); + var extensionDef = observer.ExtensionMetaData; return new ExtensionBuildMetaData { - Name = observer.ExtensionMetaData.Name, - Properties = observer.ExtensionMetaData.Properties + Name = extensionDef.Name, + ToolkitVersion = extensionDef.GetToolkitVersion(), + Properties = extensionDef.Properties }; } } @@ -149,7 +152,7 @@ public void InstallDeps() var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); StartProcessResult result = isWindows ? StartProcessUtil.Run("cmd.exe", "/c npm install", workingDirectoryPath: AppFilesPath): - StartProcessUtil.Run("npm ", "install", workingDirectoryPath: AppFilesPath); + StartProcessUtil.Run("npm", "install", workingDirectoryPath: AppFilesPath); if (result.exit != 0) { throw new CliException($"Failed to generate portal extension dependencies. \nCheck errors: \n{result.stderr} \nAll logs: {result.stdout}" diff --git a/cli/cli/Services/Web/WebClientCodeGenerator.cs b/cli/cli/Services/Web/WebClientCodeGenerator.cs index 277f31d2fe..d2baa4aaf7 100644 --- a/cli/cli/Services/Web/WebClientCodeGenerator.cs +++ b/cli/cli/Services/Web/WebClientCodeGenerator.cs @@ -62,7 +62,7 @@ public WebClientCodeGenerator(OpenApiDocument document, string langType) _clientFile.AddDeclaration(tsClass); - var tsBeamSdkImport = new TsImport("beamable-sdk"); + var tsBeamSdkImport = new TsImport("@beamable/sdk"); tsBeamSdkImport.AddNamedImport("BeamMicroServiceClient"); _clientFile.AddImport(tsBeamSdkImport); diff --git a/dev-web.sh b/dev-web.sh new file mode 100755 index 0000000000..51ee41fc86 --- /dev/null +++ b/dev-web.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +# PREREQ: +# Run ./setup-web.sh at least once before running this script. +# +# This script will be run many times as you develop web packages locally. +# Each run: +# 1. Increments the build number (stored in web-build-number.txt) +# 2. Builds and publishes @beamable/sdk and @beamable/portal-toolkit +# as version 0.0.123-local to the local Verdaccio +# registry (http://localhost:4873) +# 3. Restarts local-unpkg to bust its in-memory file cache + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WEB_SDK_DIR="$SCRIPT_DIR/web" +TOOLKIT_DIR="$SCRIPT_DIR/beam-portal-toolkit" +LOCALDEV_DIR="$SCRIPT_DIR/portal-localdev" +WEB_BUILD_NUMBER_FILE="$SCRIPT_DIR/web-build-number.txt" +REGISTRY="http://localhost:4873" + +# --------------------------------------------------------------------------- +# Cleanup trap — restores package.json files even if the script exits early +# --------------------------------------------------------------------------- +SDK_BACKUP=false +TOOLKIT_BACKUP=false + +cleanup() { + local exit_code=$? + if [ "$SDK_BACKUP" = true ]; then + echo " Restoring web/package.json..." + cp "$WEB_SDK_DIR/package.json.devbak" "$WEB_SDK_DIR/package.json" 2>/dev/null || true + rm -f "$WEB_SDK_DIR/package.json.devbak" + fi + if [ "$TOOLKIT_BACKUP" = true ]; then + echo " Restoring beam-portal-toolkit/package.json..." + cp "$TOOLKIT_DIR/package.json.devbak" "$TOOLKIT_DIR/package.json" 2>/dev/null || true + rm -f "$TOOLKIT_DIR/package.json.devbak" + fi + exit $exit_code +} +trap cleanup EXIT + +# --------------------------------------------------------------------------- +# Build number +# --------------------------------------------------------------------------- +if [ ! -f "$WEB_BUILD_NUMBER_FILE" ]; then + echo "web-build-number.txt not found. Run ./setup-web.sh first." + exit 1 +fi + +NEXT_BUILD_NUMBER=$(cat "$WEB_BUILD_NUMBER_FILE") +((NEXT_BUILD_NUMBER += 1)) +echo $NEXT_BUILD_NUMBER > "$WEB_BUILD_NUMBER_FILE" + +VERSION="0.0.123-local$NEXT_BUILD_NUMBER" + +echo "" +echo "=== Beamable Web Local Dev ===" +echo "Publishing version: $VERSION" +echo "Registry: $REGISTRY" +echo "" + +# --------------------------------------------------------------------------- +# Publish webSDK +# --------------------------------------------------------------------------- +echo "--- Building @beamable/sdk ---" +cd "$WEB_SDK_DIR" + +cp package.json package.json.devbak +SDK_BACKUP=true + +echo " [cmd] pnpm install" +pnpm install +echo " [cmd] pnpm version $VERSION --no-git-tag-version" +pnpm version "$VERSION" --no-git-tag-version +echo " [cmd] pnpm build" +pnpm build +echo " [cmd] pnpm publish --registry $REGISTRY --no-git-checks" +pnpm publish --registry "$REGISTRY" --no-git-checks + +cp package.json.devbak package.json && rm package.json.devbak +SDK_BACKUP=false + +echo "Published @beamable/sdk@$VERSION" +cd "$SCRIPT_DIR" + +# --------------------------------------------------------------------------- +# Publish toolkit +# --------------------------------------------------------------------------- +echo "" +echo "--- Building @beamable/portal-toolkit ---" +cd "$TOOLKIT_DIR" + +cp package.json package.json.devbak +TOOLKIT_BACKUP=true + +node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + pkg.peerDependencies['@beamable/sdk'] = '$VERSION'; + pkg.devDependencies['@beamable/sdk'] = '$VERSION'; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); +" +echo " Updated @beamable/sdk → $VERSION" + +# Evict any cached @beamable/sdk tarball from the pnpm content-addressable store +# AND the pnpm metadata cache. After a Verdaccio wipe the same version is +# republished with a different hash, so stale cached integrity hashes cause +# ERR_PNPM_TARBALL_INTEGRITY on the next install. +rm -f pnpm-lock.yaml +pnpm store delete @beamable/sdk 2>/dev/null || true +pnpm cache delete @beamable/sdk 2>/dev/null || true +echo " [cmd] pnpm install" +pnpm install +echo " [cmd] pnpm version $VERSION --no-git-tag-version" +pnpm version "$VERSION" --no-git-tag-version + +echo " [cmd] pnpm build" +pnpm build +echo " [cmd] pnpm publish --registry $REGISTRY --no-git-checks" +pnpm publish --registry "$REGISTRY" --no-git-checks + +cp package.json.devbak package.json && rm package.json.devbak +TOOLKIT_BACKUP=false + +echo "Published @beamable/portal-toolkit@$VERSION" +cd "$SCRIPT_DIR" + +# --------------------------------------------------------------------------- +# Restart local-unpkg to clear the in-memory file cache +# --------------------------------------------------------------------------- +echo "" +echo "--- Restarting local-unpkg (clearing file cache) ---" +docker compose -f "$LOCALDEV_DIR/docker-compose.yml" restart local-unpkg + +# --------------------------------------------------------------------------- +# Done +# --------------------------------------------------------------------------- +echo "" +echo "Done. Set ToolkitVersion: \"$VERSION\" in your extension manifest and run the Portal." diff --git a/portal-localdev/README.md b/portal-localdev/README.md new file mode 100644 index 0000000000..8098989def --- /dev/null +++ b/portal-localdev/README.md @@ -0,0 +1,200 @@ +# portal-localdev + +Local development stack for the Beamable portal extension system. + +Runs two services: + +| Service | Port | Purpose | +|---------|------|---------| +| **Verdaccio** | 4873 | Local npm registry — install packages from here instead of npmjs | +| **local-unpkg** | 4874 | CDN file server — serves individual files from Verdaccio tarballs, mirroring the unpkg.com URL format used by the Portal at runtime | + +## How the Portal knows to use local services + +Any package published as version **`0.0.123`** is treated as a local-dev build. +When the Portal sees a `ToolkitVersion` of `0.0.123` in an extension manifest, it +automatically routes all fetches for that version to `http://localhost:4874` +(local-unpkg) instead of `https://unpkg.com`. No environment variables needed. + +This extends transitively: if the local toolkit's `peerDependencies['beamable-sdk']` +is also `0.0.123`, the SDK IIFE is fetched from localhost too. If it references a +real published version like `0.6.0`, that version is still fetched from the real CDN. + +> **Port override:** `localhost:4874` is the default. Set `LOCAL_CDN_BASE_URL` in +> the Portal's `.env.local` if you run local-unpkg on a different port. + +--- + +## Prerequisites + +- [Docker Desktop](https://www.docker.com/products/docker-desktop/) (for the Docker workflow) +- OR Node.js ≥ 22 (for the non-Docker workflow) +- pnpm + +--- + +## Starting and stopping + +### With Docker (recommended) + +```bash +# Start both services in the background +docker compose up -d + +# Stop +docker compose down + +# Stop and wipe all published packages (clean slate) +docker compose down -v +``` + +### Without Docker + +```bash +# Terminal 1 — Verdaccio +npx verdaccio --config ./verdaccio/config.yml + +# Terminal 2 — local-unpkg +cd local-unpkg +npm install +node index.js +``` + +--- + +## The local dev workflow + +### Step 1 — Start the local stack + +```bash +docker compose up -d +``` + +### Step 2 — Build and publish local packages as `0.0.123` + +**Toolkit only** (testing toolkit changes with the real published SDK): + +```bash +cd beam-portal-toolkit + +# Set version to 0.0.123 in package.json (peerDependencies.beamable-sdk stays as the real version) +pnpm version 0.0.123 --no-git-tag-version + +pnpm build +pnpm publish --registry http://localhost:4873 --no-git-checks +``` + +**Toolkit + SDK** (testing both locally): + +```bash +# 1. Publish SDK as 0.0.123 +cd beamable-sdk +pnpm version 0.0.123 --no-git-tag-version +pnpm build +pnpm publish --registry http://localhost:4873 --no-git-checks + +# 2. Publish toolkit as 0.0.123, referencing local SDK +cd beam-portal-toolkit +# Update peerDependencies.beamable-sdk to "0.0.123" in package.json +pnpm version 0.0.123 --no-git-tag-version +pnpm build +pnpm publish --registry http://localhost:4873 --no-git-checks +``` + +> Verdaccio accepts re-publishing the same version. Restart `local-unpkg` after +> re-publishing to bust its in-memory file cache: +> `docker compose restart local-unpkg` + +### Step 3 — Set your extension to use `0.0.123` + +In your extension's manifest (e.g. `extension.json` or similar): + +```json +{ + "ToolkitVersion": "0.0.123" +} +``` + +In your extension's `package.json` devDependencies, point at the local registry: + +```json +{ + "devDependencies": { + "@beamable/portal-toolkit": "0.0.123", + "beamable-sdk": "0.0.123" + } +} +``` + +Then install from the local registry: + +```bash +pnpm install --registry http://localhost:4873 +``` + +Or add a `.npmrc` in the extension project: + +```ini +registry=http://localhost:4873 +``` + +Build the extension normally: + +```bash +pnpm build +``` + +### Step 4 — Run the Portal + +```bash +cd Portal +pnpm dev +``` + +That's it. No environment variables needed. The Portal detects `ToolkitVersion: "0.0.123"` +and automatically fetches from `localhost:4874`. + +--- + +## How it works + +``` +Extension manifest + └─ ToolkitVersion: "0.0.123" ← local-dev signal + │ + ▼ +Portal detects 0.0.123 → routes to http://localhost:4874 + └─ GET http://localhost:4874/@beamable/portal-toolkit@0.0.123/package.json + │ (local-unpkg fetches tarball from Verdaccio, extracts file) + ▼ + peerDependencies.beamable-sdk + + Case A — "0.6.0" (real SDK) Case B — "0.0.123" (local SDK) + │ │ + ▼ ▼ +GET https://unpkg.com/beamable-sdk@0.6.0/ GET http://localhost:4874/beamable-sdk@0.0.123/ + dist/browser/index.global.js dist/browser/index.global.js + │ │ + └──────────────┬─────────────────────┘ + ▼ + window['beamable-sdk-'] = +``` + +--- + +## Troubleshooting + +**`local-unpkg` returns 404 for a package** +The package hasn't been published to Verdaccio yet. Run `pnpm publish --registry http://localhost:4873 --no-git-checks` from the package directory. + +**Stale file after republishing** +`local-unpkg` caches files in memory. Restart it to clear the cache: +`docker compose restart local-unpkg` + +**Extension still loads from unpkg** +Check that `ToolkitVersion` in your extension manifest is exactly `0.0.123` +(or a pre-release variant like `0.0.123-1`). Any other version routes to the real CDN. + +**Port conflict** +Change the ports in `docker-compose.yml`. Add `LOCAL_CDN_BASE_URL=http://localhost:` +to the Portal's `.env.local` to override the local-dev CDN base. diff --git a/portal-localdev/docker-compose.yml b/portal-localdev/docker-compose.yml new file mode 100644 index 0000000000..13db3790d3 --- /dev/null +++ b/portal-localdev/docker-compose.yml @@ -0,0 +1,25 @@ +services: + verdaccio: + image: verdaccio/verdaccio:5 + container_name: beamable-verdaccio + ports: + - "4873:4873" + volumes: + - ./verdaccio/config.yml:/verdaccio/conf/config.yaml + - verdaccio-storage:/verdaccio/storage + environment: + - VERDACCIO_PUBLIC_URL=http://localhost:4873 + + local-unpkg: + build: ./local-unpkg + container_name: beamable-local-unpkg + ports: + - "4874:4874" + environment: + - VERDACCIO_URL=http://verdaccio:4873 + - PORT=4874 + depends_on: + - verdaccio + +volumes: + verdaccio-storage: diff --git a/portal-localdev/local-unpkg/Dockerfile b/portal-localdev/local-unpkg/Dockerfile new file mode 100644 index 0000000000..801e279d20 --- /dev/null +++ b/portal-localdev/local-unpkg/Dockerfile @@ -0,0 +1,7 @@ +FROM node:22-alpine +WORKDIR /app +COPY package.json . +RUN npm install --omit=dev +COPY index.js . +EXPOSE 4874 +CMD ["node", "index.js"] diff --git a/portal-localdev/local-unpkg/index.js b/portal-localdev/local-unpkg/index.js new file mode 100644 index 0000000000..7ca7c61360 --- /dev/null +++ b/portal-localdev/local-unpkg/index.js @@ -0,0 +1,188 @@ +#!/usr/bin/env node +/** + * local-unpkg — a minimal unpkg-compatible file server. + * + * Fetches packages from a local Verdaccio npm registry and serves individual + * files from their tarballs, mirroring the unpkg.com URL format: + * + * /{package}@{version}/{file} + * + * Examples: + * /beamable-sdk@0.6.0/dist/browser/index.global.js + * /@beamable/portal-toolkit@0.1.2/package.json + * + * All resolved files are cached in memory — restart the server to bust the + * cache (useful when re-publishing a package under the same version locally). + */ + +'use strict' + +const http = require('http') +const zlib = require('zlib') +const stream = require('stream') +const tar = require('tar-stream') + +const VERDACCIO = process.env.VERDACCIO_URL || 'http://localhost:4873' +const PORT = Number(process.env.PORT || 4874) + +// --------------------------------------------------------------------------- +// In-memory file cache — keyed by "{pkg}@{version}{/file}" +// --------------------------------------------------------------------------- +/** @type {Map} */ +const fileCache = new Map() + +// --------------------------------------------------------------------------- +// URL parsing +// --------------------------------------------------------------------------- +// Matches: +// /@scope/name@1.2.3/some/file.js +// /name@1.2.3/some/file.js +const PACKAGE_RE = /^\/((?:@[^/@]+\/)?[^/@]+)@([^/]+)(\/[^?#]*)$/ + +// --------------------------------------------------------------------------- +// Tarball extraction +// --------------------------------------------------------------------------- + +/** + * Downloads a tarball from `tarballUrl` and extracts `targetFile` from it. + * npm tarballs place all files under a `package/` prefix, which is stripped. + * + * @param {string} tarballUrl + * @param {string} targetFile e.g. "/dist/browser/index.global.js" + * @returns {Promise} + */ +function extractFileFromTarball(tarballUrl, targetFile) { + const normalTarget = targetFile.replace(/^\//, '') + + return fetch(tarballUrl).then((tarballRes) => { + if (!tarballRes.ok) { + const err = new Error(`Tarball fetch failed (${tarballRes.status}): ${tarballUrl}`) + err.status = 502 + throw err + } + + return new Promise((resolve, reject) => { + const extract = tar.extract() + let resolved = false + + extract.on('entry', (header, entryStream, next) => { + // Strip the "package/" prefix npm adds to all tarball entries + const entryPath = header.name.replace(/^package\//, '') + + if (!resolved && entryPath === normalTarget) { + resolved = true + const chunks = [] + entryStream.on('data', (c) => chunks.push(c)) + entryStream.on('end', () => { + resolve(Buffer.concat(chunks)) + next() // keep draining so the pipeline completes cleanly + }) + entryStream.on('error', reject) + } else { + entryStream.resume() + entryStream.on('end', next) + } + }) + + extract.on('finish', () => { + if (!resolved) { + const err = new Error(`File not found in tarball: ${targetFile}`) + err.status = 404 + reject(err) + } + }) + + extract.on('error', (err) => { + if (!resolved) reject(err) + }) + + const gunzip = zlib.createGunzip() + gunzip.on('error', (err) => { + if (!resolved) reject(err) + }) + + stream.Readable.fromWeb(tarballRes.body).pipe(gunzip).pipe(extract) + }) + }) +} + +// --------------------------------------------------------------------------- +// HTTP server +// --------------------------------------------------------------------------- + +const CONTENT_TYPES = { + js: 'application/javascript; charset=utf-8', + mjs: 'application/javascript; charset=utf-8', + cjs: 'application/javascript; charset=utf-8', + json: 'application/json; charset=utf-8', + ts: 'text/plain; charset=utf-8', + map: 'application/json; charset=utf-8', +} + +const server = http.createServer(async (req, res) => { + if (req.method !== 'GET' && req.method !== 'HEAD') { + res.writeHead(405).end() + return + } + + const match = PACKAGE_RE.exec(req.url ?? '/') + if (!match) { + res.writeHead(400).end('Expected /{package}@{version}/{file}') + return + } + + const [, pkg, version, filePath] = match + const cacheKey = `${pkg}@${version}${filePath}` + + try { + let content = fileCache.get(cacheKey) + + if (!content) { + // Ask Verdaccio for the specific version metadata to get the tarball URL + const metaUrl = `${VERDACCIO}/${encodeURIComponent(pkg).replace('%40', '@')}/${version}` + const metaRes = await fetch(metaUrl) + if (!metaRes.ok) { + const err = new Error(`Package not found: ${pkg}@${version}`) + err.status = metaRes.status === 404 ? 404 : 502 + throw err + } + + const meta = await metaRes.json() + // Verdaccio may return a tarball URL using the public-facing hostname + // (e.g. localhost:4873). Inside Docker that hostname points to the + // container itself, not the host. Rewrite it to the internal service name. + const rawTarballUrl = meta.dist?.tarball + const tarballUrl = rawTarballUrl?.replace(/^https?:\/\/[^/]+/, VERDACCIO) + if (!tarballUrl) { + const err = new Error(`No tarball URL in metadata for ${pkg}@${version}`) + err.status = 404 + throw err + } + + content = await extractFileFromTarball(tarballUrl, filePath) + fileCache.set(cacheKey, content) + } + + const ext = filePath.split('.').pop() ?? '' + const contentType = CONTENT_TYPES[ext] ?? 'application/octet-stream' + + res.writeHead(200, { + 'Content-Type': contentType, + 'Content-Length': String(content.length), + 'Cache-Control': 'public, max-age=31536000, immutable', + 'Access-Control-Allow-Origin': '*', + }) + + if (req.method === 'HEAD') return res.end() + res.end(content) + } catch (err) { + const status = err.status ?? 500 + console.error(`[${status}] ${cacheKey}: ${err.message}`) + res.writeHead(status).end(err.message) + } +}) + +server.listen(PORT, () => { + console.log(`local-unpkg → http://localhost:${PORT}`) + console.log(`registry → ${VERDACCIO}`) +}) diff --git a/portal-localdev/local-unpkg/package.json b/portal-localdev/local-unpkg/package.json new file mode 100644 index 0000000000..abd944f051 --- /dev/null +++ b/portal-localdev/local-unpkg/package.json @@ -0,0 +1,16 @@ +{ + "name": "local-unpkg", + "version": "1.0.0", + "private": true, + "description": "Minimal unpkg-compatible file server backed by a local Verdaccio registry", + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "engines": { + "node": ">=22" + }, + "dependencies": { + "tar-stream": "^3.1.7" + } +} diff --git a/portal-localdev/verdaccio/config.yml b/portal-localdev/verdaccio/config.yml new file mode 100644 index 0000000000..16f67ef78e --- /dev/null +++ b/portal-localdev/verdaccio/config.yml @@ -0,0 +1,28 @@ +storage: /verdaccio/storage +auth: + htpasswd: + file: /verdaccio/conf/htpasswd + # -1 means no limit, allows unauthenticated publish for local dev + max_users: -1 + +uplinks: + npmjs: + url: https://registry.npmjs.org/ + +packages: + '@beamable/*': + access: $all + publish: $all + # Do NOT proxy to npm for these — they must be published locally first. + # Comment out the proxy line if you want to fall back to npm for unpublished versions. + + '**': + access: $all + publish: $all + proxy: npmjs + +server: + keepAliveTimeout: 60 + +logs: + - { type: stdout, format: pretty, level: http } diff --git a/setup-web.sh b/setup-web.sh new file mode 100755 index 0000000000..47547baa7e --- /dev/null +++ b/setup-web.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# This script should be run ONCE before starting a local web-dev session, +# or any time you want a clean slate (wipes all previously published packages). +# +# It will: +# 1. Start the local npm registry (Verdaccio) and CDN file server (local-unpkg) +# via Docker Compose (see portal-localdev/). +# 2. Reset the web build number back to 0. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOCALDEV_DIR="$SCRIPT_DIR/portal-localdev" +WEB_BUILD_NUMBER_FILE="$SCRIPT_DIR/web-build-number.txt" + +VERDACCIO_PORT=4873 +UNPKG_PORT=4874 +VERDACCIO_URL="http://localhost:$VERDACCIO_PORT" +UNPKG_URL="http://localhost:$UNPKG_PORT" + +echo "=== Beamable Web Local Dev Setup ===" + +# --------------------------------------------------------------------------- +# Start / restart the local stack +# --------------------------------------------------------------------------- +echo "" +echo "Starting local registry and CDN server..." +docker compose -f "$LOCALDEV_DIR/docker-compose.yml" down -v # wipe old packages +docker compose -f "$LOCALDEV_DIR/docker-compose.yml" up -d + +echo "Verdaccio → $VERDACCIO_URL" +echo "local-unpkg → $UNPKG_URL" + +# --------------------------------------------------------------------------- +# Reset web build number +# --------------------------------------------------------------------------- +echo "" +echo "Resetting web build number to 0" +echo 0 > "$WEB_BUILD_NUMBER_FILE" + +# --------------------------------------------------------------------------- +# Configure global npm/pnpm registry +# --------------------------------------------------------------------------- +echo "" +echo "Pointing @beamable/* packages to local Verdaccio..." +npm config set @beamable:registry "$VERDACCIO_URL" +npm config set "//localhost:$VERDACCIO_PORT/:_authToken" local +echo " Projects resolving '@beamable/*' packages will use local Verdaccio." +echo " All other packages continue to use the default npm registry." +echo " Run ./teardown-web.sh to remove this configuration." + +echo "" +echo "Setup complete. Run ./dev-web.sh to build and publish packages." diff --git a/teardown-web.sh b/teardown-web.sh new file mode 100755 index 0000000000..15d0b7fef9 --- /dev/null +++ b/teardown-web.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Reverses the changes made by setup-web.sh: +# 1. Restores the global npm/pnpm registry to the default +# 2. Stops and wipes the local Docker stack + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOCALDEV_DIR="$SCRIPT_DIR/portal-localdev" + +echo "=== Beamable Web Local Dev Teardown ===" + +# --------------------------------------------------------------------------- +# Restore global npm/pnpm registry +# --------------------------------------------------------------------------- +echo "" +echo "Removing @beamable/* registry override..." +npm config delete @beamable:registry +npm config delete //localhost:4873/:_authToken +echo " @beamable/* packages will now resolve from the default npm registry." + +# --------------------------------------------------------------------------- +# Stop local stack +# --------------------------------------------------------------------------- +echo "" +echo "Stopping local registry and CDN server..." +docker compose -f "$LOCALDEV_DIR/docker-compose.yml" down -v + +echo "" +echo "Teardown complete." diff --git a/web/package.json b/web/package.json index 1653c9ff69..ee03708666 100644 --- a/web/package.json +++ b/web/package.json @@ -1,5 +1,5 @@ { - "name": "beamable-sdk", + "name": "@beamable/sdk", "version": "1.0.0", "description": "Beamable Web SDK", "main": "dist/node/index.cjs", @@ -59,6 +59,11 @@ "import": "./dist/schema.mjs" }, "./api": { + "browser": { + "types": "./dist/types/api.d.ts", + "require": "./dist/api.iife.js", + "import": "./dist/api.mjs" + }, "types": "./dist/types/api.d.ts", "require": "./dist/api.cjs", "import": "./dist/api.mjs"