Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/23553-default-record-page-remedy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'@objectstack/spec': patch
'@objectstack/metadata-protocol': patch
'@objectstack/runtime': patch
---

docs: the default-record-page remedies name the other package's page, not the whole package

Clause-②: no

A second `isDefault: true` record page for one object is refused with `DEFAULT_RECORD_PAGE_CONFLICT`. The package registry's refusal already told the author to keep one default or "compose the deployment without the other package's page". Three sibling texts still told them to drop the whole package, though a deployment can keep a package and leave out the one page it ships:

- `@objectstack/metadata-protocol`: the metadata save door's refusal now reads "a page a package ships stays the default unless the deployment is composed without that package's page." Only the remedy clause changed; `code`, `status`, `object` and `holders` are unchanged.
- `@objectstack/spec`: `PageSchema.isDefault`'s TSDoc and the error-code ledger's comment on `DEFAULT_RECORD_PAGE_CONFLICT` say the same.
- `@objectstack/runtime`: `AppPlugin`'s private `bundle` field now documents the three readers outside the class that read it structurally, so a rename is not made blind.

No behaviour changes; nothing to migrate.
2 changes: 1 addition & 1 deletion packages/metadata-protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21757,7 +21757,7 @@ export class ObjectStackProtocolImplementation implements
const others = named.length === 1 ? `${named[0]} already is` : `${named.join(' and ')} already are`;
const remedy = unique.some((h) => h.shipped)
? `Save '${saveName}' with \`isDefault: false\`: a page a package ships stays the default unless the `
+ `deployment is composed without that package.`
+ `deployment is composed without that package's page.`
: `Save '${saveName}' with \`isDefault: false\`, or first save ${unique.map((h) => `'${h.page}'`).join(' and ')} `
+ `with \`isDefault: false\` to make '${saveName}' the default instead.`;
const err = new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ describe.each(TOPOLOGIES)('%s kernel — a page saved as a second default record
expectRefusal(outcome, 'env_org_detail', 'acme_org', `page 'acme_org_detail' of package '${PKG}'`);
expect(String((outcome as { error?: any }).error?.message)).toContain(
"Save 'env_org_detail' with `isDefault: false`: a page a package ships stays the default unless the deployment "
+ 'is composed without that package.',
+ "is composed without that package's page.",
);
expect(storedPages()).toEqual([]);
});
Expand Down
10 changes: 10 additions & 0 deletions packages/runtime/src/app-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,16 @@ export class AppPlugin implements Plugin {
*/
requiresServices: string[] = ['manifest'];

/**
* Private to the type checker only: three readers outside this class read
* `bundle` structurally off a plugin entry, with no type to break when it
* changes. `stackDeclaresOrganizationRecordPage` (`@objectstack/core`,
* `stack-organization-record-page.ts`) looks for an app's own
* `sys_organization` record page; `@objectstack/cli`'s `serve.ts` looks for
* declared translations, and its `graft-runtime-hooks.ts` finds an app's
* bundle by manifest id to graft hooks onto. Renaming or reshaping this
* field silently blinds all three; change them together.
*/
private bundle: any;
/** Memoized backing store for {@link collections}. */
private resolvedCollections?: any;
Expand Down
2 changes: 1 addition & 1 deletion packages/spec/src/api/error-code-ledger.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ export const ERROR_CODE_LEDGER = {
// two HTTP install doors call `installPackage`. Its own code rather than
// `NAMESPACE_CONFLICT`: no name is taken — an object's one default slot is
// held — and renaming fixes nothing; the remedy is `isDefault: false` on
// one page, or composing the deployment without the other package. Not a
// one page, or composing the deployment without the other package's page. Not a
// synonym of any standard member: the manifest is well-formed, and the
// refusal comes from what the deployment already holds.
'DEFAULT_RECORD_PAGE_CONFLICT',
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/ui/page.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1871,8 +1871,8 @@ export const PageSchema = lazySchema(() => strictObject({
* objectstack#23015, record 6134056653.)
*
* To change which page opens: set `isDefault: false` on one of the two, or
* compose the deployment without the package that ships the other. Shipping
* a second default is not an override path.
* compose the deployment without the other package's page. Shipping a
* second default is not an override path.
*
* `isDefault: true` on a page that is not a record page bound to an object
* is REFUSED, at the same doors (maintainer ruling A on objectstack#23610,
Expand Down
Loading