From 514bc23144b5f0a3539663b188c1011da14bd782 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Thu, 26 Mar 2026 16:22:32 -0400 Subject: [PATCH 01/11] portal toolkit temp --- .github/workflows/release-portal-toolkit.yml | 103 + .github/workflows/release-web.yml | 47 +- beam-portal-toolkit/.gitignore | 5 + beam-portal-toolkit/custom-elements.json | 1655 +++++++++++++++++ beam-portal-toolkit/package.json | 55 + beam-portal-toolkit/pnpm-lock.yaml | 880 +++++++++ .../scripts/sync-components.mjs | 241 +++ beam-portal-toolkit/src/generated/globals.ts | 159 ++ .../src/generated/svelte-elements.ts | 145 ++ .../src/generated/web-types.json | 748 ++++++++ beam-portal-toolkit/src/index.ts | 11 + beam-portal-toolkit/src/portal.ts | 88 + beam-portal-toolkit/tsconfig.json | 20 + beam-portal-toolkit/tsdown.config.ts | 41 + beam-portal-toolkit/web-types.json | 780 ++++++++ .../templates/PortalExtensionApp/src/app.d.ts | 1 + .../PortalExtensionDiscoveryService.cs | 2 +- 17 files changed, 4966 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/release-portal-toolkit.yml create mode 100644 beam-portal-toolkit/.gitignore create mode 100644 beam-portal-toolkit/custom-elements.json create mode 100644 beam-portal-toolkit/package.json create mode 100644 beam-portal-toolkit/pnpm-lock.yaml create mode 100644 beam-portal-toolkit/scripts/sync-components.mjs create mode 100644 beam-portal-toolkit/src/generated/globals.ts create mode 100644 beam-portal-toolkit/src/generated/svelte-elements.ts create mode 100644 beam-portal-toolkit/src/generated/web-types.json create mode 100644 beam-portal-toolkit/src/index.ts create mode 100644 beam-portal-toolkit/src/portal.ts create mode 100644 beam-portal-toolkit/tsconfig.json create mode 100644 beam-portal-toolkit/tsdown.config.ts create mode 100644 beam-portal-toolkit/web-types.json create mode 100644 cli/beamable.templates/templates/PortalExtensionApp/src/app.d.ts 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..fb4486eae5 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,55 @@ 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 + + - name: Build + run: pnpm build + - 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 +120,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: Publish to npm + if: ${{ inputs.dryRun == false }} + run: pnpm publish --no-git-checks --provenance --tag ${{ steps.version.outputs.NPM_TAG }} 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/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.json b/beam-portal-toolkit/package.json new file mode 100644 index 0000000000..a7f950f0d4 --- /dev/null +++ b/beam-portal-toolkit/package.json @@ -0,0 +1,55 @@ +{ + "name": "@beamable/portal-toolkit", + "version": "0.1.1", + "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" + }, + "./svelte": { + "types": "./dist/types/svelte-elements.d.ts" + }, + "./custom-elements.json": "./custom-elements.json", + "./web-types.json": "./web-types.json" + }, + "dependencies": { + "beamable-sdk": "0.6.0" + }, + "peerDependencies": { + "svelte": ">=4.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + } + }, + "devDependencies": { + "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..adbfb6057d --- /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.1", + "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..e82f22f766 --- /dev/null +++ b/beam-portal-toolkit/src/index.ts @@ -0,0 +1,11 @@ +// Utility functions for the Beamable portal plugin 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..21041e7eef --- /dev/null +++ b/beam-portal-toolkit/src/portal.ts @@ -0,0 +1,88 @@ +// Portal plugin registration utilities. +// Import via: import { Portal } from '@beamable/portal-toolkit'; + +import { BeamBase } from "beamable-sdk"; + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +/** + * Runtime context provided by the Beamable portal to every plugin on mount. + */ +export interface PluginContext { + realm: string; + cid: string; + beam: BeamBase; +} + +/** + * Options passed to {@link Portal.registerPlugin}. + */ +export interface RegisterPluginOptions { + /** + * Unique name for the extension + */ + beamId: string; + + /** + * Called when the portal mounts this plugin 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 plugin. + * @param context - Runtime context supplied by the portal. + */ + onMount: (container: HTMLElement, context: PluginContext) => unknown | Promise; + + /** + * Called when the portal is about to remove this plugin 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 a plugin with the Beamable portal. + * + */ +function registerPlugin(options: RegisterPluginOptions): void { + + (window as unknown as Record)[options.beamId] = { + mount: (targetElement: HTMLElement, context: PluginContext) => { + 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.registerPlugin({ ... }); + * ``` + */ +export const Portal = { + registerPlugin, +} as const; 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..29b7004778 --- /dev/null +++ b/beam-portal-toolkit/tsdown.config.ts @@ -0,0 +1,41 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig([ + // CJS + ESM build + { + entry: ['src/index.ts'], + format: ['cjs', 'esm'], + outDir: 'dist', + clean: true, + dts: false, + sourcemap: false, + minify: true, + external: ['beamable-sdk'], + }, + // Type declarations + { + entry: ['src/index.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/beam-portal-toolkit/web-types.json b/beam-portal-toolkit/web-types.json new file mode 100644 index 0000000000..7cc165c1e5 --- /dev/null +++ b/beam-portal-toolkit/web-types.json @@ -0,0 +1,780 @@ +{ + "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json", + "name": "@beamable/portal-toolkit", + "version": "0.1.0", + "js-types-syntax": "typescript", + "description-markup": "markdown", + "contributions": { + "html": { + "elements": [ + { + "name": "beam-btn", + "description": "Wraps Vuetify `VBtn` as a shadow-DOM web component.", + "attributes": [ + { + "name": "color", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "outlined", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "text", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "block", + "description": "", + "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": "", + "value": { + "type": "boolean" + } + }, + { + "name": "fab", + "description": "", + "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": "", + "value": { + "type": "boolean" + } + }, + { + "name": "href", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "target", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "type", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "elevation", + "description": "", + "value": { + "type": "string" + } + } + ] + }, + { + "name": "beam-icon", + "description": "", + "attributes": [ + { + "name": "icon", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "color", + "description": "", + "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": "", + "value": { + "type": "boolean" + } + }, + { + "name": "right", + "description": "", + "value": { + "type": "boolean" + } + } + ] + }, + { + "name": "beam-chip", + "description": "Wraps Vuetify `VChip` as a shadow-DOM web component.", + "attributes": [ + { + "name": "color", + "description": "", + "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": "", + "value": { + "type": "boolean" + } + }, + { + "name": "disabled", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "label", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "pill", + "description": "", + "value": { + "type": "boolean" + } + } + ] + }, + { + "name": "beam-alert", + "description": "Wraps Vuetify `VAlert` as a shadow-DOM web component.", + "attributes": [ + { + "name": "color", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "type", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "outlined", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "text", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dense", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "dismissible", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "icon", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "border", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "elevation", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "prominent", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "tile", + "description": "", + "value": { + "type": "boolean" + } + } + ] + }, + { + "name": "beam-card", + "description": "Layout element that applies Vuetify CSS classes: `v-card`, `v-sheet`.", + "attributes": [ + { + "name": "elevation", + "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", + "value": { + "type": "number | string" + } + } + ] + }, + { + "name": "beam-card-title", + "description": "Layout element that applies Vuetify CSS classes: `v-card__title`.", + "attributes": [ + { + "name": "elevation", + "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", + "value": { + "type": "number | string" + } + } + ] + }, + { + "name": "beam-card-subtitle", + "description": "Layout element that applies Vuetify CSS classes: `v-card__subtitle`.", + "attributes": [ + { + "name": "elevation", + "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", + "value": { + "type": "number | string" + } + } + ] + }, + { + "name": "beam-card-text", + "description": "Layout element that applies Vuetify CSS classes: `v-card__text`.", + "attributes": [ + { + "name": "elevation", + "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", + "value": { + "type": "number | string" + } + } + ] + }, + { + "name": "beam-card-actions", + "description": "Layout element that applies Vuetify CSS classes: `v-card__actions`.", + "attributes": [ + { + "name": "elevation", + "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", + "value": { + "type": "number | string" + } + } + ] + }, + { + "name": "beam-data-table", + "description": "Wraps Vuetify `VDataTable` as a shadow-DOM web component.", + "attributes": [ + { + "name": "headers", + "description": "", + "value": { + "type": "array" + } + }, + { + "name": "items", + "description": "", + "value": { + "type": "array" + } + }, + { + "name": "items-per-page", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "loading", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "search", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "sort-by", + "description": "", + "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": "", + "value": { + "type": "boolean" + } + }, + { + "name": "single-select", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "value", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "dense", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "fixed-header", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "height", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "hide-default-header", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "hide-default-footer", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "no-data-text", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "no-results-text", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "dark", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "light", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "item-key", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "item-class", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "page", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "server-items-length", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "disable-pagination", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "disable-sort", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "show-expand", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "expanded", + "description": "", + "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": "", + "value": { + "type": "string" + } + }, + { + "name": "header-props", + "description": "", + "value": { + "type": "string" + } + }, + { + "name": "calculate-widths", + "description": "", + "value": { + "type": "boolean" + } + }, + { + "name": "caption", + "description": "", + "value": { + "type": "string" + } + } + ] + } + ] + } + } +} 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/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs index 73062401d7..5e96602f67 100644 --- a/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs +++ b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs @@ -149,7 +149,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}" From ae9000a6360f774552d98b602296b98bf7960d98 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Thu, 26 Mar 2026 17:35:28 -0400 Subject: [PATCH 02/11] lock --- beam-portal-toolkit/package-lock.json | 1441 +++++++++++++++++++++++++ beam-portal-toolkit/src/portal.ts | 2 +- 2 files changed, 1442 insertions(+), 1 deletion(-) create mode 100644 beam-portal-toolkit/package-lock.json 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/src/portal.ts b/beam-portal-toolkit/src/portal.ts index 21041e7eef..4b6499426b 100644 --- a/beam-portal-toolkit/src/portal.ts +++ b/beam-portal-toolkit/src/portal.ts @@ -10,7 +10,7 @@ import { BeamBase } from "beamable-sdk"; /** * Runtime context provided by the Beamable portal to every plugin on mount. */ -export interface PluginContext { +export interface PluginContext extends Map { realm: string; cid: string; beam: BeamBase; From 86d439eed1e51a478df95b2f87eae2891a770f28 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Mon, 30 Mar 2026 13:34:06 -0400 Subject: [PATCH 03/11] checkpoint --- beam-portal-toolkit/package.json | 5 +- beam-portal-toolkit/src/index.ts | 2 +- beam-portal-toolkit/src/portal.ts | 50 ++++++++++++------- .../PortalExtensionDiscoveryService.cs | 2 + 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/beam-portal-toolkit/package.json b/beam-portal-toolkit/package.json index a7f950f0d4..2d47951465 100644 --- a/beam-portal-toolkit/package.json +++ b/beam-portal-toolkit/package.json @@ -36,10 +36,8 @@ "./custom-elements.json": "./custom-elements.json", "./web-types.json": "./web-types.json" }, - "dependencies": { - "beamable-sdk": "0.6.0" - }, "peerDependencies": { + "beamable-sdk": "0.6.0", "svelte": ">=4.0.0" }, "peerDependenciesMeta": { @@ -48,6 +46,7 @@ } }, "devDependencies": { + "beamable-sdk": "0.6.0", "svelte": "^5.0.0", "tsdown": "^0.16.5", "typescript": "^5.8.3" diff --git a/beam-portal-toolkit/src/index.ts b/beam-portal-toolkit/src/index.ts index e82f22f766..84f155a325 100644 --- a/beam-portal-toolkit/src/index.ts +++ b/beam-portal-toolkit/src/index.ts @@ -1,4 +1,4 @@ -// Utility functions for the Beamable portal plugin system. +// 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 diff --git a/beam-portal-toolkit/src/portal.ts b/beam-portal-toolkit/src/portal.ts index 4b6499426b..fbc495fb88 100644 --- a/beam-portal-toolkit/src/portal.ts +++ b/beam-portal-toolkit/src/portal.ts @@ -1,44 +1,44 @@ -// Portal plugin registration utilities. +// Portal extension registration utilities. // Import via: import { Portal } from '@beamable/portal-toolkit'; -import { BeamBase } from "beamable-sdk"; +import { Beam, BeamBase } from "beamable-sdk"; // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- /** - * Runtime context provided by the Beamable portal to every plugin on mount. + * Runtime context provided by the Beamable portal to every extension on mount. */ -export interface PluginContext extends Map { +export interface ExtensionContext extends Map { realm: string; cid: string; - beam: BeamBase; + beam: Promise; } /** - * Options passed to {@link Portal.registerPlugin}. + * Options passed to {@link Portal.registerExtension}. */ -export interface RegisterPluginOptions { +export interface RegisterExtensionOptions { /** * Unique name for the extension */ beamId: string; /** - * Called when the portal mounts this plugin into the DOM. + * 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 plugin. + * + * @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: PluginContext) => unknown | Promise; + onMount: (container: HTMLElement, context: ExtensionContext) => unknown | Promise; /** - * Called when the portal is about to remove this plugin from the DOM. + * 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 @@ -54,13 +54,27 @@ export interface RegisterPluginOptions { // --------------------------------------------------------------------------- /** - * Registers a plugin with the Beamable portal. + * 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 registerPlugin(options: RegisterPluginOptions): void { +function registerExtension(options: RegisterExtensionOptions): void { (window as unknown as Record)[options.beamId] = { - mount: (targetElement: HTMLElement, context: PluginContext) => { + mount: (targetElement: HTMLElement, context: ExtensionContext) => { return options.onMount(targetElement, context); }, unmount: (instance: unknown) => { @@ -80,9 +94,9 @@ function registerPlugin(options: RegisterPluginOptions): void { * @example * ```ts * import { Portal } from '@beamable/portal-toolkit'; - * Portal.registerPlugin({ ... }); + * Portal.registerExtension({ ... }); * ``` */ export const Portal = { - registerPlugin, + registerExtension, } as const; diff --git a/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs index 5e96602f67..937ebca2c5 100644 --- a/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs +++ b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs @@ -25,6 +25,8 @@ namespace cli.Services.PortalExtension; public class ExtensionBuildMetaData { public string Name; + public string ToolkitVersion; + public string WebSDKVersion; public PortalExtensionPackageProperties Properties; } From 232e943e5be2aa9662b7e004d91b5126917c5205 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Mon, 30 Mar 2026 15:57:09 -0400 Subject: [PATCH 04/11] updates --- beam-portal-toolkit/README.md | 180 ++++++++++++++++++ beam-portal-toolkit/package.json | 12 +- .../src/generated/web-types.json | 2 +- beam-portal-toolkit/src/rollup.ts | 47 +++++ beam-portal-toolkit/src/vite.ts | 59 ++++++ beam-portal-toolkit/tsdown.config.ts | 6 +- .../templates/PortalExtensionApp/package.json | 4 +- .../PortalExtensionApp/src/App.svelte | 29 ++- .../templates/PortalExtensionApp/src/main.js | 25 ++- .../PortalExtensionApp/vite.config.js | 8 +- cli/cli/Services/BeamoLocalSystem.cs | 35 +++- .../PortalExtensionDiscoveryService.cs | 7 +- 12 files changed, 378 insertions(+), 36 deletions(-) create mode 100644 beam-portal-toolkit/README.md create mode 100644 beam-portal-toolkit/src/rollup.ts create mode 100644 beam-portal-toolkit/src/vite.ts diff --git a/beam-portal-toolkit/README.md b/beam-portal-toolkit/README.md new file mode 100644 index 0000000000..af6e817126 --- /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/package.json b/beam-portal-toolkit/package.json index 2d47951465..46165d6895 100644 --- a/beam-portal-toolkit/package.json +++ b/beam-portal-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@beamable/portal-toolkit", - "version": "0.1.1", + "version": "0.1.2", "description": "Beamable Portal Toolkit — utilities and web component types for the Beamable portal plugin system", "main": "dist/index.cjs", "module": "dist/index.mjs", @@ -30,6 +30,16 @@ "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" }, diff --git a/beam-portal-toolkit/src/generated/web-types.json b/beam-portal-toolkit/src/generated/web-types.json index adbfb6057d..6a95c429a2 100644 --- a/beam-portal-toolkit/src/generated/web-types.json +++ b/beam-portal-toolkit/src/generated/web-types.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json", "name": "@beamable/portal-toolkit", - "version": "0.1.1", + "version": "0.1.2", "js-types-syntax": "typescript", "description-markup": "markdown", "contributions": { diff --git a/beam-portal-toolkit/src/rollup.ts b/beam-portal-toolkit/src/rollup.ts new file mode 100644 index 0000000000..112a2af920 --- /dev/null +++ b/beam-portal-toolkit/src/rollup.ts @@ -0,0 +1,47 @@ +/** + * Rollup config helpers for Beamable portal extensions. + * + * Provides pre-configured external/globals options so that `beamable-sdk` + * is excluded from the extension bundle and resolved to the versioned window + * global 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, + * } + * + * When the toolkit's beamable-sdk peer dependency version changes, update + * SDK_GLOBAL below to match. + * + * Note: only the main `beamable-sdk` entry is externalized. The subpath + * `beamable-sdk/api` has no browser IIFE build and is stateless (no shared + * connection or auth state), so it is safe — and correct — to bundle it + * directly into the extension. Do not add it to externals/globals. + */ + +// Versioned global name the Portal registers on window before the extension +// script runs. Must match the `globalName` in the Portal's beam-sdk-registry. +const SDK_GLOBAL = 'beamable-sdk-0.6.0' + +/** + * 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'] as const, + output: { + globals: { + 'beamable-sdk': `window['${SDK_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..bdf33c34dd --- /dev/null +++ b/beam-portal-toolkit/src/vite.ts @@ -0,0 +1,59 @@ +/** + * Vite plugin for Beamable portal extensions. + * + * Configures the build so that `beamable-sdk` is treated as an external and + * resolved to the versioned window global 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', + * }, + * }, + * }) + * + * When the toolkit's beamable-sdk peer dependency version changes, update + * SDK_GLOBAL below to match. + * + * Note: only the main `beamable-sdk` entry is externalized. The subpath + * `beamable-sdk/api` has no browser IIFE build and is stateless (no shared + * connection or auth state), so it is safe — and correct — to bundle it + * directly into the extension. Do not add it to externals/globals. + */ + +// Versioned global name the Portal registers on window before the extension +// script runs. Must match the `globalName` in the Portal's beam-sdk-registry. +const SDK_GLOBAL = 'beamable-sdk-0.6.0' + +/** + * Returns a Vite plugin that marks `beamable-sdk` as external and maps it + * to the Portal-provided window global at runtime. + */ +export function portalExtensionPlugin() { + return { + name: 'beamable-portal-extension', + config() { + return { + build: { + rollupOptions: { + external: ['beamable-sdk'], + output: { + globals: { + 'beamable-sdk': `window['${SDK_GLOBAL}']`, + }, + }, + }, + }, + } + }, + } +} diff --git a/beam-portal-toolkit/tsdown.config.ts b/beam-portal-toolkit/tsdown.config.ts index 29b7004778..1e1f246632 100644 --- a/beam-portal-toolkit/tsdown.config.ts +++ b/beam-portal-toolkit/tsdown.config.ts @@ -1,9 +1,9 @@ import { defineConfig } from 'tsdown'; export default defineConfig([ - // CJS + ESM build + // CJS + ESM build — runtime + build-tool entry points { - entry: ['src/index.ts'], + entry: ['src/index.ts', 'src/vite.ts', 'src/rollup.ts'], format: ['cjs', 'esm'], outDir: 'dist', clean: true, @@ -14,7 +14,7 @@ export default defineConfig([ }, // Type declarations { - entry: ['src/index.ts'], + entry: ['src/index.ts', 'src/vite.ts', 'src/rollup.ts'], outDir: 'dist/types', clean: false, dts: { 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/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 937ebca2c5..b1a34175c3 100644 --- a/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs +++ b/cli/cli/Services/PortalExtension/PortalExtensionDiscoveryService.cs @@ -26,7 +26,6 @@ public class ExtensionBuildMetaData { public string Name; public string ToolkitVersion; - public string WebSDKVersion; public PortalExtensionPackageProperties Properties; } @@ -60,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 }; } } From 9ba01bdb617dd50c2d0ce766c85601abe2a84ff4 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Mon, 30 Mar 2026 16:05:55 -0400 Subject: [PATCH 05/11] web types cleanup --- beam-portal-toolkit/package.json | 2 +- beam-portal-toolkit/web-types.json | 780 ----------------------------- 2 files changed, 1 insertion(+), 781 deletions(-) delete mode 100644 beam-portal-toolkit/web-types.json diff --git a/beam-portal-toolkit/package.json b/beam-portal-toolkit/package.json index 46165d6895..2c6a1e77e2 100644 --- a/beam-portal-toolkit/package.json +++ b/beam-portal-toolkit/package.json @@ -44,7 +44,7 @@ "types": "./dist/types/svelte-elements.d.ts" }, "./custom-elements.json": "./custom-elements.json", - "./web-types.json": "./web-types.json" + "./web-types.json": "./src/generated/web-types.json" }, "peerDependencies": { "beamable-sdk": "0.6.0", diff --git a/beam-portal-toolkit/web-types.json b/beam-portal-toolkit/web-types.json deleted file mode 100644 index 7cc165c1e5..0000000000 --- a/beam-portal-toolkit/web-types.json +++ /dev/null @@ -1,780 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json", - "name": "@beamable/portal-toolkit", - "version": "0.1.0", - "js-types-syntax": "typescript", - "description-markup": "markdown", - "contributions": { - "html": { - "elements": [ - { - "name": "beam-btn", - "description": "Wraps Vuetify `VBtn` as a shadow-DOM web component.", - "attributes": [ - { - "name": "color", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "outlined", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "text", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "block", - "description": "", - "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": "", - "value": { - "type": "boolean" - } - }, - { - "name": "fab", - "description": "", - "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": "", - "value": { - "type": "boolean" - } - }, - { - "name": "href", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "target", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "type", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "elevation", - "description": "", - "value": { - "type": "string" - } - } - ] - }, - { - "name": "beam-icon", - "description": "", - "attributes": [ - { - "name": "icon", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "color", - "description": "", - "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": "", - "value": { - "type": "boolean" - } - }, - { - "name": "right", - "description": "", - "value": { - "type": "boolean" - } - } - ] - }, - { - "name": "beam-chip", - "description": "Wraps Vuetify `VChip` as a shadow-DOM web component.", - "attributes": [ - { - "name": "color", - "description": "", - "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": "", - "value": { - "type": "boolean" - } - }, - { - "name": "disabled", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "dark", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "light", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "label", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "pill", - "description": "", - "value": { - "type": "boolean" - } - } - ] - }, - { - "name": "beam-alert", - "description": "Wraps Vuetify `VAlert` as a shadow-DOM web component.", - "attributes": [ - { - "name": "color", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "type", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "outlined", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "text", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "dense", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "dismissible", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "icon", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "border", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "elevation", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "dark", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "light", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "prominent", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "tile", - "description": "", - "value": { - "type": "boolean" - } - } - ] - }, - { - "name": "beam-card", - "description": "Layout element that applies Vuetify CSS classes: `v-card`, `v-sheet`.", - "attributes": [ - { - "name": "elevation", - "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", - "value": { - "type": "number | string" - } - } - ] - }, - { - "name": "beam-card-title", - "description": "Layout element that applies Vuetify CSS classes: `v-card__title`.", - "attributes": [ - { - "name": "elevation", - "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", - "value": { - "type": "number | string" - } - } - ] - }, - { - "name": "beam-card-subtitle", - "description": "Layout element that applies Vuetify CSS classes: `v-card__subtitle`.", - "attributes": [ - { - "name": "elevation", - "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", - "value": { - "type": "number | string" - } - } - ] - }, - { - "name": "beam-card-text", - "description": "Layout element that applies Vuetify CSS classes: `v-card__text`.", - "attributes": [ - { - "name": "elevation", - "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", - "value": { - "type": "number | string" - } - } - ] - }, - { - "name": "beam-card-actions", - "description": "Layout element that applies Vuetify CSS classes: `v-card__actions`.", - "attributes": [ - { - "name": "elevation", - "description": "Vuetify elevation (0–24). Maps to `elevation-N` CSS class.", - "value": { - "type": "number | string" - } - } - ] - }, - { - "name": "beam-data-table", - "description": "Wraps Vuetify `VDataTable` as a shadow-DOM web component.", - "attributes": [ - { - "name": "headers", - "description": "", - "value": { - "type": "array" - } - }, - { - "name": "items", - "description": "", - "value": { - "type": "array" - } - }, - { - "name": "items-per-page", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "loading", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "search", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "sort-by", - "description": "", - "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": "", - "value": { - "type": "boolean" - } - }, - { - "name": "single-select", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "value", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "dense", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "fixed-header", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "height", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "hide-default-header", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "hide-default-footer", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "no-data-text", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "no-results-text", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "dark", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "light", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "item-key", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "item-class", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "page", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "server-items-length", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "disable-pagination", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "disable-sort", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "show-expand", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "expanded", - "description": "", - "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": "", - "value": { - "type": "string" - } - }, - { - "name": "header-props", - "description": "", - "value": { - "type": "string" - } - }, - { - "name": "calculate-widths", - "description": "", - "value": { - "type": "boolean" - } - }, - { - "name": "caption", - "description": "", - "value": { - "type": "string" - } - } - ] - } - ] - } - } -} From dd59c8556ff9b1be337532ab19f570cbd2ce9d50 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Tue, 31 Mar 2026 07:58:03 -0400 Subject: [PATCH 06/11] fix: derive SDK_GLOBAL from package.json version and fix web-types.json export path - vite.ts / rollup.ts: compute SDK_GLOBAL dynamically from peerDependencies instead of hardcoding - package.json: point ./web-types.json export to src/generated/web-types.json (was missing at root) Co-Authored-By: Claude Sonnet 4.6 --- beam-portal-toolkit/src/rollup.ts | 7 +++---- beam-portal-toolkit/src/vite.ts | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/beam-portal-toolkit/src/rollup.ts b/beam-portal-toolkit/src/rollup.ts index 112a2af920..97f66005ab 100644 --- a/beam-portal-toolkit/src/rollup.ts +++ b/beam-portal-toolkit/src/rollup.ts @@ -20,18 +20,17 @@ * external: portalExtensionRollupOptions.external, * } * - * When the toolkit's beamable-sdk peer dependency version changes, update - * SDK_GLOBAL below to match. - * * Note: only the main `beamable-sdk` entry is externalized. The subpath * `beamable-sdk/api` has no browser IIFE build and is stateless (no shared * connection or auth state), so it is safe — and correct — to bundle it * directly into the extension. Do not add it to externals/globals. */ +import pkg from '../package.json' + // Versioned global name the Portal registers on window before the extension // script runs. Must match the `globalName` in the Portal's beam-sdk-registry. -const SDK_GLOBAL = 'beamable-sdk-0.6.0' +const SDK_GLOBAL = `beamable-sdk-${pkg.peerDependencies['beamable-sdk']}` /** * Spread `external` into the top-level rollup config and `output` into the diff --git a/beam-portal-toolkit/src/vite.ts b/beam-portal-toolkit/src/vite.ts index bdf33c34dd..dcfce7d0e0 100644 --- a/beam-portal-toolkit/src/vite.ts +++ b/beam-portal-toolkit/src/vite.ts @@ -21,18 +21,17 @@ * }, * }) * - * When the toolkit's beamable-sdk peer dependency version changes, update - * SDK_GLOBAL below to match. - * * Note: only the main `beamable-sdk` entry is externalized. The subpath * `beamable-sdk/api` has no browser IIFE build and is stateless (no shared * connection or auth state), so it is safe — and correct — to bundle it * directly into the extension. Do not add it to externals/globals. */ +import pkg from '../package.json' + // Versioned global name the Portal registers on window before the extension // script runs. Must match the `globalName` in the Portal's beam-sdk-registry. -const SDK_GLOBAL = 'beamable-sdk-0.6.0' +const SDK_GLOBAL = `beamable-sdk-${pkg.peerDependencies['beamable-sdk']}` /** * Returns a Vite plugin that marks `beamable-sdk` as external and maps it From 8d58c4569573daf146b7cc3f5822d7f31105bbd9 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Tue, 31 Mar 2026 09:12:14 -0400 Subject: [PATCH 07/11] work --- .gitignore | 4 +- dev-web.sh | 140 ++++++++++++++++ portal-localdev/README.md | 200 +++++++++++++++++++++++ portal-localdev/docker-compose.yml | 25 +++ portal-localdev/local-unpkg/Dockerfile | 7 + portal-localdev/local-unpkg/index.js | 184 +++++++++++++++++++++ portal-localdev/local-unpkg/package.json | 16 ++ portal-localdev/verdaccio/config.yml | 32 ++++ setup-web.sh | 38 +++++ 9 files changed, 645 insertions(+), 1 deletion(-) create mode 100755 dev-web.sh create mode 100644 portal-localdev/README.md create mode 100644 portal-localdev/docker-compose.yml create mode 100644 portal-localdev/local-unpkg/Dockerfile create mode 100644 portal-localdev/local-unpkg/index.js create mode 100644 portal-localdev/local-unpkg/package.json create mode 100644 portal-localdev/verdaccio/config.yml create mode 100755 setup-web.sh 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/dev-web.sh b/dev-web.sh new file mode 100755 index 0000000000..eec71bb35c --- /dev/null +++ b/dev-web.sh @@ -0,0 +1,140 @@ +#!/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 packages as version 0.0.123. +# to the local Verdaccio registry (http://localhost:4873) +# 3. Restarts local-unpkg to bust its in-memory file cache +# +# By default both the webSDK (beamable-sdk) and toolkit (@beamable/portal-toolkit) +# are built and published. Use --skip-sdk to publish the toolkit only. +# +# When --skip-sdk is used the toolkit's peerDependencies.beamable-sdk is left +# unchanged, so the Portal will load that SDK version from the real CDN. +# When the SDK is also published the toolkit's peer dependency is updated to the +# local version so the Portal loads both from localhost. + +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" + +# --------------------------------------------------------------------------- +# Flags +# --------------------------------------------------------------------------- +SKIP_SDK=false + +while test $# -gt 0; do + case "$1" in + --skip-sdk) + SKIP_SDK=true + echo "Skipping webSDK build — toolkit will reference its current peerDependency version" + ;; + *) + echo "Unknown argument: $1" + ;; + esac + shift +done + +# --------------------------------------------------------------------------- +# 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") +PREVIOUS_BUILD_NUMBER=$NEXT_BUILD_NUMBER +((NEXT_BUILD_NUMBER += 1)) +echo $NEXT_BUILD_NUMBER > "$WEB_BUILD_NUMBER_FILE" + +VERSION="0.0.123.$NEXT_BUILD_NUMBER" +PREVIOUS_VERSION="0.0.123.$PREVIOUS_BUILD_NUMBER" + +echo "" +echo "=== Beamable Web Local Dev ===" +echo "Publishing version: $VERSION" +echo "Registry: $REGISTRY" +echo "" + +# --------------------------------------------------------------------------- +# Publish webSDK +# --------------------------------------------------------------------------- +if [ "$SKIP_SDK" = false ]; then + echo "--- Building beamable-sdk ---" + cd "$WEB_SDK_DIR" + + # Temporarily set the version, build, publish, then restore + SAVED_SDK_VERSION=$(node -p "require('./package.json').version") + pnpm version "$VERSION" --no-git-tag-version + pnpm build + pnpm publish --registry "$REGISTRY" --no-git-checks + + # Restore the original version + pnpm version "$SAVED_SDK_VERSION" --no-git-tag-version + + echo "Published beamable-sdk@$VERSION" + cd "$SCRIPT_DIR" +fi + +# --------------------------------------------------------------------------- +# Publish toolkit +# --------------------------------------------------------------------------- +echo "" +echo "--- Building @beamable/portal-toolkit ---" +cd "$TOOLKIT_DIR" + +# Temporarily set the toolkit version (and optionally peerDep), then restore +SAVED_TOOLKIT_VERSION=$(node -p "require('./package.json').version") +SAVED_TOOLKIT_PEER=$(node -p "require('./package.json').peerDependencies['beamable-sdk']") +pnpm version "$VERSION" --no-git-tag-version + +# If the SDK was also published locally, update the peer dependency to match +# so the Portal knows to load both from localhost. +if [ "$SKIP_SDK" = false ]; then + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + pkg.peerDependencies['beamable-sdk'] = '$VERSION'; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); + " + echo "Updated peerDependencies.beamable-sdk → $VERSION" +fi + +pnpm build +pnpm publish --registry "$REGISTRY" --no-git-checks + +# Restore version and peerDep to their original values +pnpm version "$SAVED_TOOLKIT_VERSION" --no-git-tag-version +node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + pkg.peerDependencies['beamable-sdk'] = '$SAVED_TOOLKIT_PEER'; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); +" + +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..4bbef00ae9 --- /dev/null +++ b/portal-localdev/local-unpkg/index.js @@ -0,0 +1,184 @@ +#!/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() + const tarballUrl = meta.dist?.tarball + 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..930f1c157e --- /dev/null +++ b/portal-localdev/verdaccio/config.yml @@ -0,0 +1,32 @@ +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. + + 'beamable-sdk': + access: $all + publish: $all + + '**': + 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..a510feb95d --- /dev/null +++ b/setup-web.sh @@ -0,0 +1,38 @@ +#!/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" + +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 → http://localhost:4873" +echo "local-unpkg → http://localhost:4874" + +# --------------------------------------------------------------------------- +# Reset web build number +# --------------------------------------------------------------------------- +echo "" +echo "Resetting web build number to 0" +echo 0 > "$WEB_BUILD_NUMBER_FILE" + +echo "" +echo "Setup complete. Run ./dev-web.sh to build and publish packages." From d0238ace8e08ebcc289add71e3063f91ece06615 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Tue, 31 Mar 2026 16:48:07 -0400 Subject: [PATCH 08/11] local flow working --- .github/workflows/release-web.yml | 12 ++-- beam-portal-toolkit/.npmrc | 3 + beam-portal-toolkit/README.md | 12 ++-- beam-portal-toolkit/package.json | 4 +- beam-portal-toolkit/src/index.ts | 2 +- beam-portal-toolkit/src/portal.ts | 2 +- beam-portal-toolkit/src/rollup.ts | 12 ++-- beam-portal-toolkit/src/vite.ts | 14 ++--- beam-portal-toolkit/tsdown.config.ts | 4 +- dev-web.sh | 91 +++++++++++++++++++--------- portal-localdev/local-unpkg/index.js | 6 +- portal-localdev/verdaccio/config.yml | 4 -- setup-web.sh | 11 ++++ teardown-web.sh | 31 ++++++++++ web/package.json | 2 +- 15 files changed, 144 insertions(+), 66 deletions(-) create mode 100644 beam-portal-toolkit/.npmrc create mode 100755 teardown-web.sh diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index fb4486eae5..0a5ba45f65 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -99,8 +99,10 @@ jobs: - name: Set package version run: npm version ${{ steps.version.outputs.VERSION }} --no-git-tag-version - - name: Build - run: pnpm build + # 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 }} @@ -120,6 +122,6 @@ jobs: "production": "production" }')[github.event.inputs.releaseType] }} - - name: Publish to npm - if: ${{ inputs.dryRun == false }} - run: pnpm publish --no-git-checks --provenance --tag ${{ steps.version.outputs.NPM_TAG }} + - name: Dry run build + if: ${{ inputs.dryRun == true }} + run: pnpm prepublishOnly diff --git a/beam-portal-toolkit/.npmrc b/beam-portal-toolkit/.npmrc new file mode 100644 index 0000000000..6c9b3d9bb6 --- /dev/null +++ b/beam-portal-toolkit/.npmrc @@ -0,0 +1,3 @@ +# Route @beamable/* to the local Verdaccio registry (mirrors what setup-web.sh does globally) +@beamable:registry=http://localhost:4873 +//localhost:4873/:_authToken=local diff --git a/beam-portal-toolkit/README.md b/beam-portal-toolkit/README.md index af6e817126..4be5c80570 100644 --- a/beam-portal-toolkit/README.md +++ b/beam-portal-toolkit/README.md @@ -5,7 +5,7 @@ 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 +- **Re-exports** of `@beamable/sdk` types --- @@ -13,18 +13,18 @@ Utilities and type definitions for building Beamable portal extensions. ```bash npm install @beamable/portal-toolkit -# beamable-sdk is a peer dependency — install it too -npm install beamable-sdk +# @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: +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'], + external: ['@beamable/sdk'], }, }, }; @@ -174,7 +174,7 @@ You must be logged in to npm (`npm login`) with publish rights to the `@beamable | Import path | Contents | |---|---| -| `@beamable/portal-toolkit` | `Portal` namespace, all `beamable-sdk` types, web component globals | +| `@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/package.json b/beam-portal-toolkit/package.json index 2c6a1e77e2..42bec29e79 100644 --- a/beam-portal-toolkit/package.json +++ b/beam-portal-toolkit/package.json @@ -47,7 +47,7 @@ "./web-types.json": "./src/generated/web-types.json" }, "peerDependencies": { - "beamable-sdk": "0.6.0", + "@beamable/sdk": "1.0.0", "svelte": ">=4.0.0" }, "peerDependenciesMeta": { @@ -56,7 +56,7 @@ } }, "devDependencies": { - "beamable-sdk": "0.6.0", + "@beamable/sdk": "1.0.0", "svelte": "^5.0.0", "tsdown": "^0.16.5", "typescript": "^5.8.3" diff --git a/beam-portal-toolkit/src/index.ts b/beam-portal-toolkit/src/index.ts index 84f155a325..3658f403eb 100644 --- a/beam-portal-toolkit/src/index.ts +++ b/beam-portal-toolkit/src/index.ts @@ -7,5 +7,5 @@ // `pnpm sync-components` to refresh it from Portal's beam-components.json. import './generated/globals'; -export * from 'beamable-sdk'; +export * from '@beamable/sdk'; export * from './portal'; diff --git a/beam-portal-toolkit/src/portal.ts b/beam-portal-toolkit/src/portal.ts index fbc495fb88..ae01344a25 100644 --- a/beam-portal-toolkit/src/portal.ts +++ b/beam-portal-toolkit/src/portal.ts @@ -1,7 +1,7 @@ // Portal extension registration utilities. // Import via: import { Portal } from '@beamable/portal-toolkit'; -import { Beam, BeamBase } from "beamable-sdk"; +import { Beam, BeamBase } from "@beamable/sdk"; // --------------------------------------------------------------------------- // Types diff --git a/beam-portal-toolkit/src/rollup.ts b/beam-portal-toolkit/src/rollup.ts index 97f66005ab..094d36ad44 100644 --- a/beam-portal-toolkit/src/rollup.ts +++ b/beam-portal-toolkit/src/rollup.ts @@ -1,7 +1,7 @@ /** * Rollup config helpers for Beamable portal extensions. * - * Provides pre-configured external/globals options so that `beamable-sdk` + * Provides pre-configured external/globals options so that `@beamable/sdk` * is excluded from the extension bundle and resolved to the versioned window * global that the Portal injects before running the extension script. * @@ -20,8 +20,8 @@ * external: portalExtensionRollupOptions.external, * } * - * Note: only the main `beamable-sdk` entry is externalized. The subpath - * `beamable-sdk/api` has no browser IIFE build and is stateless (no shared + * Note: only the main `@beamable/sdk` entry is externalized. The subpath + * `@beamable/sdk/api` has no browser IIFE build and is stateless (no shared * connection or auth state), so it is safe — and correct — to bundle it * directly into the extension. Do not add it to externals/globals. */ @@ -30,17 +30,17 @@ import pkg from '../package.json' // Versioned global name the Portal registers on window before the extension // script runs. Must match the `globalName` in the Portal's beam-sdk-registry. -const SDK_GLOBAL = `beamable-sdk-${pkg.peerDependencies['beamable-sdk']}` +const SDK_GLOBAL = `@beamable/sdk-${pkg.peerDependencies['@beamable/sdk']}` /** * 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'] as const, + external: ['@beamable/sdk'] as const, output: { globals: { - 'beamable-sdk': `window['${SDK_GLOBAL}']`, + '@beamable/sdk': `window['${SDK_GLOBAL}']`, }, }, } as const diff --git a/beam-portal-toolkit/src/vite.ts b/beam-portal-toolkit/src/vite.ts index dcfce7d0e0..acabce6e26 100644 --- a/beam-portal-toolkit/src/vite.ts +++ b/beam-portal-toolkit/src/vite.ts @@ -1,7 +1,7 @@ /** * Vite plugin for Beamable portal extensions. * - * Configures the build so that `beamable-sdk` is treated as an external and + * Configures the build so that `@beamable/sdk` is treated as an external and * resolved to the versioned window global that the Portal injects before * running the extension script. * @@ -21,8 +21,8 @@ * }, * }) * - * Note: only the main `beamable-sdk` entry is externalized. The subpath - * `beamable-sdk/api` has no browser IIFE build and is stateless (no shared + * Note: only the main `@beamable/sdk` entry is externalized. The subpath + * `@beamable/sdk/api` has no browser IIFE build and is stateless (no shared * connection or auth state), so it is safe — and correct — to bundle it * directly into the extension. Do not add it to externals/globals. */ @@ -31,10 +31,10 @@ import pkg from '../package.json' // Versioned global name the Portal registers on window before the extension // script runs. Must match the `globalName` in the Portal's beam-sdk-registry. -const SDK_GLOBAL = `beamable-sdk-${pkg.peerDependencies['beamable-sdk']}` +const SDK_GLOBAL = `@beamable/sdk-${pkg.peerDependencies['@beamable/sdk']}` /** - * Returns a Vite plugin that marks `beamable-sdk` as external and maps it + * Returns a Vite plugin that marks `@beamable/sdk` as external and maps it * to the Portal-provided window global at runtime. */ export function portalExtensionPlugin() { @@ -44,10 +44,10 @@ export function portalExtensionPlugin() { return { build: { rollupOptions: { - external: ['beamable-sdk'], + external: ['@beamable/sdk'], output: { globals: { - 'beamable-sdk': `window['${SDK_GLOBAL}']`, + '@beamable/sdk': `window['${SDK_GLOBAL}']`, }, }, }, diff --git a/beam-portal-toolkit/tsdown.config.ts b/beam-portal-toolkit/tsdown.config.ts index 1e1f246632..269614d774 100644 --- a/beam-portal-toolkit/tsdown.config.ts +++ b/beam-portal-toolkit/tsdown.config.ts @@ -10,7 +10,7 @@ export default defineConfig([ dts: false, sourcemap: false, minify: true, - external: ['beamable-sdk'], + external: ['@beamable/sdk'], }, // Type declarations { @@ -23,7 +23,7 @@ export default defineConfig([ outExtensions: () => ({ dts: '.d.ts', }), - external: ['beamable-sdk', 'svelte'], + external: ['@beamable/sdk', 'svelte'], }, // Svelte element type augmentations { diff --git a/dev-web.sh b/dev-web.sh index eec71bb35c..d88f5279a1 100755 --- a/dev-web.sh +++ b/dev-web.sh @@ -6,17 +6,17 @@ # 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 packages as version 0.0.123. +# 2. Builds and publishes packages 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 # -# By default both the webSDK (beamable-sdk) and toolkit (@beamable/portal-toolkit) +# By default both the webSDK (@beamable/sdk) and toolkit (@beamable/portal-toolkit) # are built and published. Use --skip-sdk to publish the toolkit only. # -# When --skip-sdk is used the toolkit's peerDependencies.beamable-sdk is left -# unchanged, so the Portal will load that SDK version from the real CDN. -# When the SDK is also published the toolkit's peer dependency is updated to the -# local version so the Portal loads both from localhost. +# When --skip-sdk is used, the toolkit's package.json is left untouched — +# the developer is responsible for the declared @beamable/sdk version. +# When the SDK is also published, both peer and dev dependency are updated to +# the local version so the Portal loads both from localhost. set -e @@ -27,6 +27,28 @@ 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 + # --------------------------------------------------------------------------- # Flags # --------------------------------------------------------------------------- @@ -58,8 +80,8 @@ PREVIOUS_BUILD_NUMBER=$NEXT_BUILD_NUMBER ((NEXT_BUILD_NUMBER += 1)) echo $NEXT_BUILD_NUMBER > "$WEB_BUILD_NUMBER_FILE" -VERSION="0.0.123.$NEXT_BUILD_NUMBER" -PREVIOUS_VERSION="0.0.123.$PREVIOUS_BUILD_NUMBER" +VERSION="0.0.123-local$NEXT_BUILD_NUMBER" +PREVIOUS_VERSION="0.0.123-local$PREVIOUS_BUILD_NUMBER" echo "" echo "=== Beamable Web Local Dev ===" @@ -71,19 +93,25 @@ echo "" # Publish webSDK # --------------------------------------------------------------------------- if [ "$SKIP_SDK" = false ]; then - echo "--- Building beamable-sdk ---" + echo "--- Building @beamable/sdk ---" cd "$WEB_SDK_DIR" - # Temporarily set the version, build, publish, then restore - SAVED_SDK_VERSION=$(node -p "require('./package.json').version") + 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 - # Restore the original version - pnpm version "$SAVED_SDK_VERSION" --no-git-tag-version + cp package.json.devbak package.json && rm package.json.devbak + SDK_BACKUP=false - echo "Published beamable-sdk@$VERSION" + echo "Published @beamable/sdk@$VERSION" cd "$SCRIPT_DIR" fi @@ -94,34 +122,37 @@ echo "" echo "--- Building @beamable/portal-toolkit ---" cd "$TOOLKIT_DIR" -# Temporarily set the toolkit version (and optionally peerDep), then restore -SAVED_TOOLKIT_VERSION=$(node -p "require('./package.json').version") -SAVED_TOOLKIT_PEER=$(node -p "require('./package.json').peerDependencies['beamable-sdk']") -pnpm version "$VERSION" --no-git-tag-version +cp package.json package.json.devbak +TOOLKIT_BACKUP=true -# If the SDK was also published locally, update the peer dependency to match -# so the Portal knows to load both from localhost. +# When the SDK is also published this run, update both devDependencies and +# peerDependencies to the local version BEFORE pnpm install, so pnpm resolves +# @beamable/sdk from Verdaccio correctly. +# When --skip-sdk is passed, package.json is left untouched — the developer +# is responsible for ensuring the declared version is available. if [ "$SKIP_SDK" = false ]; then node -e " const fs = require('fs'); const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); - pkg.peerDependencies['beamable-sdk'] = '$VERSION'; + pkg.peerDependencies['@beamable/sdk'] = '$VERSION'; + pkg.devDependencies['@beamable/sdk'] = '$VERSION'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); " - echo "Updated peerDependencies.beamable-sdk → $VERSION" + echo " Updated @beamable/sdk → $VERSION" fi +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 -# Restore version and peerDep to their original values -pnpm version "$SAVED_TOOLKIT_VERSION" --no-git-tag-version -node -e " - const fs = require('fs'); - const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); - pkg.peerDependencies['beamable-sdk'] = '$SAVED_TOOLKIT_PEER'; - fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); -" +cp package.json.devbak package.json && rm package.json.devbak +TOOLKIT_BACKUP=false echo "Published @beamable/portal-toolkit@$VERSION" cd "$SCRIPT_DIR" diff --git a/portal-localdev/local-unpkg/index.js b/portal-localdev/local-unpkg/index.js index 4bbef00ae9..7ca7c61360 100644 --- a/portal-localdev/local-unpkg/index.js +++ b/portal-localdev/local-unpkg/index.js @@ -148,7 +148,11 @@ const server = http.createServer(async (req, res) => { } const meta = await metaRes.json() - const tarballUrl = meta.dist?.tarball + // 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 diff --git a/portal-localdev/verdaccio/config.yml b/portal-localdev/verdaccio/config.yml index 930f1c157e..16f67ef78e 100644 --- a/portal-localdev/verdaccio/config.yml +++ b/portal-localdev/verdaccio/config.yml @@ -16,10 +16,6 @@ packages: # 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. - 'beamable-sdk': - access: $all - publish: $all - '**': access: $all publish: $all diff --git a/setup-web.sh b/setup-web.sh index a510feb95d..bae553e9f7 100755 --- a/setup-web.sh +++ b/setup-web.sh @@ -34,5 +34,16 @@ 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 http://localhost:4873 +npm config set //localhost:4873/:_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..228daf6269 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", From 786d9d6fd224b295cd90eb90d72cddbe934c57dc Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Tue, 31 Mar 2026 19:29:49 -0400 Subject: [PATCH 09/11] update --- beam-portal-toolkit/.npmrc | 3 --- beam-portal-toolkit/package.json | 2 +- dev-web.sh | 5 +++++ 3 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 beam-portal-toolkit/.npmrc diff --git a/beam-portal-toolkit/.npmrc b/beam-portal-toolkit/.npmrc deleted file mode 100644 index 6c9b3d9bb6..0000000000 --- a/beam-portal-toolkit/.npmrc +++ /dev/null @@ -1,3 +0,0 @@ -# Route @beamable/* to the local Verdaccio registry (mirrors what setup-web.sh does globally) -@beamable:registry=http://localhost:4873 -//localhost:4873/:_authToken=local diff --git a/beam-portal-toolkit/package.json b/beam-portal-toolkit/package.json index 42bec29e79..fcdc66c5d0 100644 --- a/beam-portal-toolkit/package.json +++ b/beam-portal-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@beamable/portal-toolkit", - "version": "0.1.2", + "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", diff --git a/dev-web.sh b/dev-web.sh index d88f5279a1..29348f64da 100755 --- a/dev-web.sh +++ b/dev-web.sh @@ -141,6 +141,11 @@ if [ "$SKIP_SDK" = false ]; then echo " Updated @beamable/sdk → $VERSION" fi +# Evict any cached @beamable/sdk tarball from the pnpm content-addressable store. +# After a Verdaccio wipe the same version is republished with a different hash, +# so the cached tarball causes ERR_PNPM_TARBALL_INTEGRITY on the next install. +rm -f pnpm-lock.yaml +pnpm store delete @beamable/sdk 2>/dev/null || true echo " [cmd] pnpm install" pnpm install echo " [cmd] pnpm version $VERSION --no-git-tag-version" From 47a4146e141bf0a3015998592ee46289fd735481 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Wed, 1 Apr 2026 15:57:04 -0400 Subject: [PATCH 10/11] fixes --- README.md | 7 ++ beam-portal-toolkit/src/rollup.ts | 19 ++- beam-portal-toolkit/src/vite.ts | 24 ++-- .../Services/Web/WebClientCodeGenerator.cs | 2 +- dev-web.sh | 108 ++++++------------ setup-web.sh | 13 ++- 6 files changed, 74 insertions(+), 99 deletions(-) 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/src/rollup.ts b/beam-portal-toolkit/src/rollup.ts index 094d36ad44..2745e58c62 100644 --- a/beam-portal-toolkit/src/rollup.ts +++ b/beam-portal-toolkit/src/rollup.ts @@ -2,8 +2,9 @@ * Rollup config helpers for Beamable portal extensions. * * Provides pre-configured external/globals options so that `@beamable/sdk` - * is excluded from the extension bundle and resolved to the versioned window - * global that the Portal injects before running the extension script. + * 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: * @@ -19,28 +20,26 @@ * }, * external: portalExtensionRollupOptions.external, * } - * - * Note: only the main `@beamable/sdk` entry is externalized. The subpath - * `@beamable/sdk/api` has no browser IIFE build and is stateless (no shared - * connection or auth state), so it is safe — and correct — to bundle it - * directly into the extension. Do not add it to externals/globals. */ import pkg from '../package.json' -// Versioned global name the Portal registers on window before the extension +// 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_GLOBAL = `@beamable/sdk-${pkg.peerDependencies['@beamable/sdk']}` +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'] as const, + 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 index acabce6e26..940724ee63 100644 --- a/beam-portal-toolkit/src/vite.ts +++ b/beam-portal-toolkit/src/vite.ts @@ -1,9 +1,9 @@ /** * Vite plugin for Beamable portal extensions. * - * Configures the build so that `@beamable/sdk` is treated as an external and - * resolved to the versioned window global that the Portal injects before - * running the extension script. + * 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: * @@ -20,22 +20,19 @@ * }, * }, * }) - * - * Note: only the main `@beamable/sdk` entry is externalized. The subpath - * `@beamable/sdk/api` has no browser IIFE build and is stateless (no shared - * connection or auth state), so it is safe — and correct — to bundle it - * directly into the extension. Do not add it to externals/globals. */ import pkg from '../package.json' -// Versioned global name the Portal registers on window before the extension +// 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_GLOBAL = `@beamable/sdk-${pkg.peerDependencies['@beamable/sdk']}` +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` as external and maps it - * to the Portal-provided window global at runtime. + * 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 { @@ -44,10 +41,11 @@ export function portalExtensionPlugin() { return { build: { rollupOptions: { - external: ['@beamable/sdk'], + external: ['@beamable/sdk', '@beamable/sdk/api'], output: { globals: { '@beamable/sdk': `window['${SDK_GLOBAL}']`, + '@beamable/sdk/api': `window['${SDK_API_GLOBAL}']`, }, }, }, 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 index 29348f64da..51ee41fc86 100755 --- a/dev-web.sh +++ b/dev-web.sh @@ -6,17 +6,10 @@ # 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 packages as version 0.0.123-local -# to the local Verdaccio registry (http://localhost:4873) +# 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 -# -# By default both the webSDK (@beamable/sdk) and toolkit (@beamable/portal-toolkit) -# are built and published. Use --skip-sdk to publish the toolkit only. -# -# When --skip-sdk is used, the toolkit's package.json is left untouched — -# the developer is responsible for the declared @beamable/sdk version. -# When the SDK is also published, both peer and dev dependency are updated to -# the local version so the Portal loads both from localhost. set -e @@ -49,24 +42,6 @@ cleanup() { } trap cleanup EXIT -# --------------------------------------------------------------------------- -# Flags -# --------------------------------------------------------------------------- -SKIP_SDK=false - -while test $# -gt 0; do - case "$1" in - --skip-sdk) - SKIP_SDK=true - echo "Skipping webSDK build — toolkit will reference its current peerDependency version" - ;; - *) - echo "Unknown argument: $1" - ;; - esac - shift -done - # --------------------------------------------------------------------------- # Build number # --------------------------------------------------------------------------- @@ -76,12 +51,10 @@ if [ ! -f "$WEB_BUILD_NUMBER_FILE" ]; then fi NEXT_BUILD_NUMBER=$(cat "$WEB_BUILD_NUMBER_FILE") -PREVIOUS_BUILD_NUMBER=$NEXT_BUILD_NUMBER ((NEXT_BUILD_NUMBER += 1)) echo $NEXT_BUILD_NUMBER > "$WEB_BUILD_NUMBER_FILE" VERSION="0.0.123-local$NEXT_BUILD_NUMBER" -PREVIOUS_VERSION="0.0.123-local$PREVIOUS_BUILD_NUMBER" echo "" echo "=== Beamable Web Local Dev ===" @@ -92,28 +65,26 @@ echo "" # --------------------------------------------------------------------------- # Publish webSDK # --------------------------------------------------------------------------- -if [ "$SKIP_SDK" = false ]; then - 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" -fi +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 @@ -125,27 +96,22 @@ cd "$TOOLKIT_DIR" cp package.json package.json.devbak TOOLKIT_BACKUP=true -# When the SDK is also published this run, update both devDependencies and -# peerDependencies to the local version BEFORE pnpm install, so pnpm resolves -# @beamable/sdk from Verdaccio correctly. -# When --skip-sdk is passed, package.json is left untouched — the developer -# is responsible for ensuring the declared version is available. -if [ "$SKIP_SDK" = false ]; then - 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" -fi - -# Evict any cached @beamable/sdk tarball from the pnpm content-addressable store. -# After a Verdaccio wipe the same version is republished with a different hash, -# so the cached tarball causes ERR_PNPM_TARBALL_INTEGRITY on the next install. +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" diff --git a/setup-web.sh b/setup-web.sh index bae553e9f7..47547baa7e 100755 --- a/setup-web.sh +++ b/setup-web.sh @@ -14,6 +14,11 @@ 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 ===" # --------------------------------------------------------------------------- @@ -24,8 +29,8 @@ 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 → http://localhost:4873" -echo "local-unpkg → http://localhost:4874" +echo "Verdaccio → $VERDACCIO_URL" +echo "local-unpkg → $UNPKG_URL" # --------------------------------------------------------------------------- # Reset web build number @@ -39,8 +44,8 @@ echo 0 > "$WEB_BUILD_NUMBER_FILE" # --------------------------------------------------------------------------- echo "" echo "Pointing @beamable/* packages to local Verdaccio..." -npm config set @beamable:registry http://localhost:4873 -npm config set //localhost:4873/:_authToken local +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." From d0fb5e88442e8737ee82337a5fad162ff9f3f912 Mon Sep 17 00:00:00 2001 From: Chris Hanna Date: Wed, 1 Apr 2026 16:12:12 -0400 Subject: [PATCH 11/11] package fix --- .github/workflows/deployWebSample.yml | 3 +-- build/bin/upload-web-sdk-sample-build.sh | 2 +- web/package.json | 5 +++++ 3 files changed, 7 insertions(+), 3 deletions(-) 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/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/web/package.json b/web/package.json index 228daf6269..ee03708666 100644 --- a/web/package.json +++ b/web/package.json @@ -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"