Skip to content

chore(release): version packages - #1

Merged
drav0011 merged 1 commit into
mainfrom
changeset-release/main
Sep 20, 2026
Merged

drav0011 merged 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@bedrock-core/config@0.3.0

Minor Changes

  • e69758e Thanks @drav0011! - Breaking. The UI is three peer apps, and each one is a field of core.register().

    @bedrock-core/config was the addon list, the config screens and the guide viewer in one mount.
    Those are three different things to want, so they are three packages: @bedrock-core/catalog
    browses every addon in the world, @bedrock-core/config holds an addon's settings and the screens
    that edit them, and @bedrock-core/guides shows its guide. Each installs on its own.

    // before
    import { ui } from '@bedrock-core/config';
    import { config } from '@bedrock-core/config/server';
    
    core.register({ manifest, config: config(definition) });
    ui(core); // the list, the config screens, the guide, and four commands
    
    // after
    import { registerCatalog } from '@bedrock-core/catalog';
    import { registerConfig } from '@bedrock-core/config';
    import { registerGuides } from '@bedrock-core/guides/server';
    
    const { config } = core.register({
      manifest,
      catalog: registerCatalog(),
      config: registerConfig(definition),
      guides: registerGuides(),
    });

    register() is the whole mount — there is no second call, and taking two of the three is dropping
    a field rather than passing a flag. Each declaration installs its own command, serves its own
    core:<app>.show method and announces that this addon offers that app, so what a realm can do for
    a player follows from what the addon asked for.

    A declaration takes only what the build cannot work out for itself. registerConfig(definition)
    takes the definition because the definition is the declaration: the runtime installs the scopes
    from it and the ui-compiler filter reads it out of that very call to shape one screen per section.
    registerCatalog() and registerGuides() take nothing at all — the roster is core.registry, and
    the guide's pages are already compiled into the pack — so their presence is the entire statement.
    Each also takes { commands: false }, which frees the command name without unmounting the app.

    Each app owns one command, under the addon's own namespace: <ns>:config and <ns>:configat stay
    here, <ns>:catalog belongs to the catalog (<ns>:list is gone — vanilla owns /list, and the
    alias Bedrock grants the first registrant cannot be claimed for a name it already has), and
    <ns>:guide belongs to the guide app.

    Removed from @bedrock-core/config, with where each went:

    • ui, openUi and UiOptions — registerConfig() mounts, and config.open(player, target?) on
      the returned accessor is the funnel that openUi was. The permission clamp is still behind it.
    • addonPageScreen and AddonPageInfo — the page is AddonPage and AddonPageInfo on
      @bedrock-core/catalog/compiled; the addon list, the framework's own row and the page geometry
      are internal to the catalog.
    • guideAudienceFor — removed.
    • registerDeclared and DeclaredParts — @bedrock-core/navigation.
    • registerAddonCommands, OpenCallback, allowedScopes, clampTarget, isOperator,
      CONFIG_SCOPES, ConfigScope, EntrySchema and FlatSchemaLike — internal.
      registerConfig(definition, { commands: false }) with config.open(player, target?) makes your
      own entry point, and isOperator is @bedrock-core/server's.

    @bedrock-core/config/server renames its field factory config to registerConfig, matching the
    name the root exports: the two are the same field, one with screens and one without, and an addon
    that draws nothing imports the subpath alone. The subsystem reaches the runtime through a
    namespaced slot rather than a fixed property — configOf(core) reads what the declaration filled
    under core:config.

    @bedrock-core/guides gains @bedrock-core/guides/server, the guide app's server half:
    registerGuides, guidesOf and their types. It runs on a bare Runtime and draws nothing. The
    package root re-exports it beside the screen factories the guides filter's generated modules call,
    openGuide and GuideComponents. GuideBlockList, resolveLanding, canSee,
    hasVisiblePages, paginationFor, visiblePageIds, visibleTree, isGuideManifest,
    guideScreenName and the manifest types are internal: a guide renders from what the filter
    compiles.

  • ea00fe0 Thanks @drav0011! - Breaking. Every screen the config UI draws is compiled into the pack. App, AppProps, AppRoutes and AppScreen are removed from @bedrock-core/config.

  • e69758e Thanks @drav0011! - Breaking. A screen is drawn by the addon whose pack holds it, and a crossing carries the way
    back.

    A config target naming another addon is handed to that addon's realm before anything is drawn:
    the screens read and write the addon's own scopes, so its settings, its page and its guide are
    served by it. No realm draws another addon's settings.

    Config is local. configOf(core).of(), configOf(core).subscribe(), RemoteConfigAccessor,
    TypedRemoteConfig, ConfigAccessOptions, the nine core:config.<scope>.<get|patch|set> RPC
    methods and the core-config/schema and core-config/groups announcements are gone, and
    configOf(core).local gains groups. An addon that wants its settings read or written from
    another realm serves them over its own RPC.

    One method does all of it, core:ui.show(playerId, target, returnTo?), and the third argument is
    what makes a crossing survivable. A return address names a PLACE rather than a screen key — a
    list, a menu level and a roster are each drawn from a model, and rendering their component with no
    model draws the empty shape of the screen. Each hop carries the whole way back in the request, so
    a chain of any depth walks home through the realms it came through rather than dead-ending on the
    far side.

    A row whose realm does not answer is still drawn here, from the page reference that addon
    published, exactly as before. Handing off is what happens when the owner is present, not a
    requirement for appearing at all.

    The open target is now one per app rather than one shared union, and internal to it.
    isOpenTarget, OpenTarget and OpenCommand are gone — a target crosses a realm as plain
    data, and each app reads its own. A realm running an older copy understands as much of a target as
    it knows and falls back for the rest.

    The permission clamp applies on arrival rather than at the entry points. A target also arrives
    from the wire, where no caller in this realm has applied it, so a non-operator cannot reach past
    their own player scope even when the request says otherwise.

  • ea00fe0 Thanks @drav0011! - An addon's screens follow from what it declared.

    core.register() is read at build time, and what follows from it is compiled: one config screen per section of the declared schema — shaped for the settings that section has, each drawn as the control it is, with its label baked — and the addon's page in the shared list, drawn from its manifest. A list's items get a screen of their own, with the options a present offers filled in rather than baked.

    There is no cap on rows or options, because a screen serving any schema is the only thing that needed one.

  • 514e866 Thanks @drav0011! - Breaking. The enum entry type is select, and EnumEntry is SelectEntry. A list is free
    strings only: itemType and options are gone from it, and a setting drawn from a fixed set is a
    multiselect.

    A select and a multiselect take options as a string array or a string enum, and both infer
    from them: a select reads back as one of its options, and a multiselect as an array of them where
    it read back as string[]. EntryOptions and OptionValue are exported beside the entry types.

  • e69758e Thanks @drav0011! - A setting is drawn as the control it is, showing what is actually stored.

    A shaped leaf reads the scope's stored document rather than the schema's defaults. Values are
    nested the way the schema is while a field is named by its flat path, so each one is read down its
    path and falls back to what the schema declares only where nothing is set. A section deep-linked
    from a command fetches before its first render, so it opens on the values in the world instead of
    on defaults it then has to correct.

    Each row takes the shape vanilla gives that control, inside full-width dividers:

    • a toggle sits beside its caption and note;
    • a slider sits under its caption and note, with the value at the caption's end;
    • every other control takes the note after it.

    A short enum is a segmented control and a longer one stays a dropdown. A multiselect draws a
    checkbox per option, answering under <key>#<n>, and the host folds those back into the array —
    clearing the last box yields an empty array rather than dropping the setting. Save writes and then
    goes back; dismissing goes back without writing. A list returns to the section holding it rather
    than to the scope root, and the list editor re-presents with its patch merged down the setting's
    own path.

    Screen bodies share one rect inside the card's border, so the insets read equal from one screen to
    the next, and an addon page keeps a narrower right inset beside the scroll gutter.

  • ea00fe0 Thanks @drav0011! - A guide page ships as a table, not as a component.

    A guide page is a static screen: every string it shows is baked and every press it takes is a <Link>. GuideBlockList, GuidePageView, GuideHomeView and the guide manifest are absent from a built addon, and opening a page is one form call. openGuide(ns, player) no longer takes the manifest: it navigates to the guide's key, and the manifest is build input that never reaches the addon. A cmp block in a guide may not take a press: somewhere to go is a <Link>, anything else is decoration.

@bedrock-core/guides@0.2.0

Minor Changes

  • e69758e Thanks @drav0011! - A guide opens on its home page, and every page is one press from the index.

    guide_home is where a guide opens: the page marked home: true, the only page of a single-page
    guide, or the index when there is neither. guide_home_back is the same entry with a back control,
    what a host that opened the guide shows in its place. guide_index is the index itself, compiled
    once, and exported as guideIndexScreen.

    Moving inside a guide replaces rather than stacks. A page's back and its index button both open
    guide_index in the page's place, and a row of the index opens its page in the index's place. In a
    guide with a home page the index's back opens guide_home_back in its place, and the home page's
    own back leads to wherever the guide was opened from; in a guide with none, the index's back does.
    A reader who followed six links is one press from the index. A single-page guide has no index
    button, and its back leaves the guide.

    The screen names live in their own module, exported from the package root. The half that BUILDS
    the screens and the half that FINDS them in another addon's pack must agree exactly, since a key is
    <namespace>:<name> and the two never meet at runtime.

  • e69758e Thanks @drav0011! - Breaking. The UI is three peer apps, and each one is a field of core.register().

    @bedrock-core/config was the addon list, the config screens and the guide viewer in one mount.
    Those are three different things to want, so they are three packages: @bedrock-core/catalog
    browses every addon in the world, @bedrock-core/config holds an addon's settings and the screens
    that edit them, and @bedrock-core/guides shows its guide. Each installs on its own.

    // before
    import { ui } from '@bedrock-core/config';
    import { config } from '@bedrock-core/config/server';
    
    core.register({ manifest, config: config(definition) });
    ui(core); // the list, the config screens, the guide, and four commands
    
    // after
    import { registerCatalog } from '@bedrock-core/catalog';
    import { registerConfig } from '@bedrock-core/config';
    import { registerGuides } from '@bedrock-core/guides/server';
    
    const { config } = core.register({
      manifest,
      catalog: registerCatalog(),
      config: registerConfig(definition),
      guides: registerGuides(),
    });

    register() is the whole mount — there is no second call, and taking two of the three is dropping
    a field rather than passing a flag. Each declaration installs its own command, serves its own
    core:<app>.show method and announces that this addon offers that app, so what a realm can do for
    a player follows from what the addon asked for.

    A declaration takes only what the build cannot work out for itself. registerConfig(definition)
    takes the definition because the definition is the declaration: the runtime installs the scopes
    from it and the ui-compiler filter reads it out of that very call to shape one screen per section.
    registerCatalog() and registerGuides() take nothing at all — the roster is core.registry, and
    the guide's pages are already compiled into the pack — so their presence is the entire statement.
    Each also takes { commands: false }, which frees the command name without unmounting the app.

    Each app owns one command, under the addon's own namespace: <ns>:config and <ns>:configat stay
    here, <ns>:catalog belongs to the catalog (<ns>:list is gone — vanilla owns /list, and the
    alias Bedrock grants the first registrant cannot be claimed for a name it already has), and
    <ns>:guide belongs to the guide app.

    Removed from @bedrock-core/config, with where each went:

    • ui, openUi and UiOptions — registerConfig() mounts, and config.open(player, target?) on
      the returned accessor is the funnel that openUi was. The permission clamp is still behind it.
    • addonPageScreen and AddonPageInfo — the page is AddonPage and AddonPageInfo on
      @bedrock-core/catalog/compiled; the addon list, the framework's own row and the page geometry
      are internal to the catalog.
    • guideAudienceFor — removed.
    • registerDeclared and DeclaredParts — @bedrock-core/navigation.
    • registerAddonCommands, OpenCallback, allowedScopes, clampTarget, isOperator,
      CONFIG_SCOPES, ConfigScope, EntrySchema and FlatSchemaLike — internal.
      registerConfig(definition, { commands: false }) with config.open(player, target?) makes your
      own entry point, and isOperator is @bedrock-core/server's.

    @bedrock-core/config/server renames its field factory config to registerConfig, matching the
    name the root exports: the two are the same field, one with screens and one without, and an addon
    that draws nothing imports the subpath alone. The subsystem reaches the runtime through a
    namespaced slot rather than a fixed property — configOf(core) reads what the declaration filled
    under core:config.

    @bedrock-core/guides gains @bedrock-core/guides/server, the guide app's server half:
    registerGuides, guidesOf and their types. It runs on a bare Runtime and draws nothing. The
    package root re-exports it beside the screen factories the guides filter's generated modules call,
    openGuide and GuideComponents. GuideBlockList, resolveLanding, canSee,
    hasVisiblePages, paginationFor, visiblePageIds, visibleTree, isGuideManifest,
    guideScreenName and the manifest types are internal: a guide renders from what the filter
    compiles.

  • ccd175f Thanks @drav0011! - Breaking. A paragraph or list item with links is drawn with Trans: the build breaks it into the same number of lines in every language, and each link is pressable only where its own text is drawn, in whichever language the client shows. The manifest's GuideRun is gone. An inline block carries k when it has no links, and when it has, text — a tagged string by locale, See <0>the page</0>. — and links, the page each numbered tag opens, matching the guides filter that writes it.

  • ccd175f Thanks @drav0011! - A page or category marked access: op is shown to world operators only.

    A guide with anything gated is compiled once per audience. guide_home, guide_home_back,
    guide_index and guide_<page> are what every player is shown: a gated page has no screen there,
    the index lists only what a player may open, prev and next skip what they may not, a gated home
    page is no home to them, and a link to a gated page, in a paragraph, a list, an admonition or a
    component's children, is drawn as text. guideop_home, guideop_home_back, guideop_index and
    guideop_<page> are the operators' set: every page, and every press inside it leads within it. A
    guide with nothing gated compiles the ordinary set alone.

    The entry decides which set a reader walks. guides.open(player, addonId?), the <ns>:guide
    command, a catalog's guide button and openGuide(ns, player) open an operator on the operators'
    set when the guide has one, and everyone else on the ordinary set. A <Link> to guide_home or
    guide_home_back is the same press for every viewer, so it always opens the ordinary set.
    openGuide(ns, player, { back: true }) opens the entry with a back control, in the set the player
    reads, for a screen that links to a guide.

    The screen factories take audience: 'op' for the operators' set, which is what the guides filter
    writes, and the manifest carries opScreens, each page's screen name in that set.

  • ea00fe0 Thanks @drav0011! - Breaking. A guide is its compiled screens, navigated by key.

    createGuide is removed: a page is a screen rather than a state of one. guideReference, presentGuideReference, isGuideReference and GuideReference go with it, because a guide's screens ride the ordinary screen table. openGuide(ns, player) is a navigate(), so it opens this bundle's guide or another addon's the same way. The views take link keys (linkTo, homeTo) instead of open-page callbacks.

  • ea00fe0 Thanks @drav0011! - A guide page ships as a table, not as a component.

    A guide page is a static screen: every string it shows is baked and every press it takes is a <Link>. GuideBlockList, GuidePageView, GuideHomeView and the guide manifest are absent from a built addon, and opening a page is one form call. openGuide(ns, player) no longer takes the manifest: it navigates to the guide's key, and the manifest is build input that never reaches the addon. A cmp block in a guide may not take a press: somewhere to go is a <Link>, anything else is decoration.

@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 4b09613 to 31dd66b Compare September 20, 2026 17:32
@drav0011
drav0011 merged commit 6d6d853 into main Sep 20, 2026
1 check passed
@drav0011
drav0011 deleted the changeset-release/main branch September 20, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant