Skip to content

Conversation

@findolor
Copy link
Collaborator

@findolor findolor commented Dec 1, 2025

Chained PR

Dependent PR

Motivation

See issues:

Now that we have everything in place for the registry implementation in webapp, this PR does just that.

Solution

  • Web app bootstrap now loads the dotrain registry via WASM (DotrainRegistry) and builds RaindexClient from the registry’s embedded settings instead of fetching a standalone YAML

  • Deploy flows read order/deployment details directly from the registry and pass them through the route hierarchy, eliminating per-component DotrainOrderGui fetches and the old handleGuiInitialization helper

  • Registry/order validation tests were rewritten around the new registry-driven data flow, simplifying component tests to consume provided props and removing the old async mocks

  • Settings backend now tracks full document sets on ScenarioCfg, provides default_documents(), caches remote tokens on the orderbook YAML, and surfaces clearer missing-field errors for networks/orderbooks/orders

  • Tauri commands were updated to pass the new scenario docs

fix #2078

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Summary by CodeRabbit

Release Notes

  • New Features

    • Added registry URL override support via ?registry= query parameter with persistent storage.
    • Introduced support for multiple YAML documents in scenario configurations.
  • Improvements

    • Refactored order and deployment data loading to use a registry-based system for improved reliability.
    • Enhanced error messages for network and configuration issues.
    • Streamlined UI component data handling with cleaner prop-based architecture.
  • Bug Fixes

    • Fixed remote token cache synchronization across orderbook and YAML layers.

✏️ Tip: You can customize this high-level summary in your review settings.

@findolor findolor requested review from 0xgleb and hardyjosh December 1, 2025 13:20
@findolor findolor self-assigned this Dec 1, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Multiple crates and packages are updated to integrate registry-based data loading and introduce multi-document YAML support for scenarios. Data flows shift from direct static method calls and manual fetching to centralized registry provider patterns, with error handling refined across parsing and initialization paths.

Changes

Cohort / File(s) Summary
Multi-document YAML support
crates/settings/src/yaml/mod.rs, crates/settings/src/scenario.rs, crates/settings/src/deployment.rs, crates/settings/src/unit_test.rs, tauri-app/src-tauri/src/commands/order.rs
Added public documents field and default_documents() function to enable scenarios to hold multiple YAML documents alongside a single document, with initialization and serialization adjustments throughout.
Registry-based page initialization
packages/webapp/src/routes/+layout.ts, packages/webapp/src/routes/+layout.svelte
Introduced DotrainRegistry and RegistryManager into layout. Registry now loaded via URL parameter or localStorage, with RaindexClient and local database initialization dependent on successful registry loading.
Deploy route data loading refactoring
packages/webapp/src/routes/deploy/+layout.ts, packages/webapp/src/routes/deploy/[orderName]/+layout.ts, packages/webapp/src/routes/deploy/[orderName]/[deploymentKey]/+layout.ts
Replaced direct registry URL fetching and validateOrders logic with registry-from-parent pattern; deployments and order details now derived from registry methods instead of manual construction.
GUI initialization refactoring
packages/webapp/src/lib/services/handleGuiInitialization.ts (deleted), packages/webapp/src/routes/deploy/[orderName]/[deploymentKey]/+page.svelte
Removed handleGuiInitialization module entirely; GUI creation now via registry.getGui() with callback for URL state history.
UI component data prop refactoring
packages/ui-components/src/lib/components/deployment/DeploymentsSection.svelte, packages/ui-components/src/lib/components/deployment/OrderPage.svelte, packages/ui-components/src/lib/__mocks__/stores.ts
Replaced fetching and DotrainOrderGui usage with direct deployments and orderDetail props; components now data-driven instead of async-fetching.
Registry validation integration
packages/ui-components/src/lib/services/loadRegistryUrl.ts, packages/ui-components/src/__tests__/loadRegistryUrl.test.ts
Replaced fetchRegistryDotrains with DotrainRegistry.validate(url) for registry URL validation.
Error handling refinements
crates/settings/src/network.rs, crates/settings/src/order.rs, crates/settings/src/orderbook.rs
Updated network/order/orderbook parsing to use explicit early-exit guards and improved error types (e.g., Missing instead of InvalidType for absent keys).
Remote token cache synchronization
crates/common/src/dotrain_order.rs
Added cache update to OrderbookYaml alongside DotrainYaml after fetching remote tokens in create_with_profile.
Comprehensive test rewrites
packages/webapp/src/__tests__/handleGuiInitialization.test.ts (deleted), packages/webapp/src/routes/deploy/[orderName]/[deploymentKey]/fullDeployment.test.ts, packages/webapp/src/routes/deploy/[orderName]/[deploymentKey]/page.test.ts, packages/webapp/src/routes/deploy/[orderName]/layout.test.ts, packages/ui-components/src/__tests__/DeploymentsSection.test.ts, packages/ui-components/src/__tests__/OrderPage.test.ts
Tests removed, rewritten, or refactored to mock registry instead of DotrainOrderGui; removed async fetching mocks; updated component render expectations to use new data props.
Constants and documentation updates
packages/webapp/src/lib/constants.ts, packages/webapp/ARCHITECTURE.md
Removed REMOTE_SETTINGS_URL; updated REGISTRY_URL commit hash; updated documentation to reflect registry-based initialization flow.

Sequence Diagram

sequenceDiagram
    participant App as App/+layout.svelte
    participant Registry as DotrainRegistry
    participant Manager as RegistryManager
    participant DeployLayout as deploy/+layout.ts
    participant OrderLayout as deploy/[orderName]/+layout.ts
    participant OrderPage as OrderPage.svelte
    participant UI as DeploymentsSection

    Note over App,UI: Previous Flow (Removed)
    App->>App: fetch registry & dotrains via URL
    App->>DotrainOrderGui: newFromState/newWithDeployment
    
    Note over App,UI: New Flow (Current)
    App->>Registry: Registry.new(url)
    App->>Manager: RegistryManager(url)
    App->>App: Store registry & manager in context
    
    DeployLayout->>Registry: getAllOrderDetails()
    Registry-->>DeployLayout: validOrders, invalidOrders
    
    OrderLayout->>Registry: getDeploymentDetails(orderName)
    Registry-->>OrderLayout: deployments map
    
    OrderLayout->>OrderPage: Pass orderDetail, deployments
    
    OrderPage->>UI: Pass deployments prop
    UI->>UI: Render deployments from prop (no fetch)
    
    OrderPage->>Registry: getGui(orderName, deploymentKey)
    Registry-->>OrderPage: GUI instance
    OrderPage->>OrderPage: Render GUI with markdown
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–75 minutes

  • High complexity areas requiring close attention:
    • packages/webapp/src/routes/+layout.ts — Registry initialization, localStorage persistence, and error propagation logic; changed from { fetch } to { url } parameter handling
    • packages/webapp/src/routes/deploy/[orderName]/[deploymentKey]/+page.svelte — Removal of handleGuiInitialization and shift to registry.getGui() call patterns; state and error handling refactoring
    • crates/settings/src/scenario.rs — Multi-document field propagation and parsing flow changes; affects serialization/deserialization
    • crates/settings/src/network.rs, order.rs, orderbook.rs — Guard-based error handling changes and error type substitutions (InvalidType → Missing); ensure all edge cases are covered
    • Test files (page.test.ts, fullDeployment.test.ts) — Extensive mock restructuring; verify mock behavior aligns with real registry interface
    • packages/ui-components/src/lib/components/deployment/{DeploymentsSection,OrderPage}.svelte — Props refactoring; ensure data flows correctly through hierarchy

Possibly related PRs

  • PR #1913 — Modifies DotrainOrderGui API and construction patterns; this PR replaces those static method calls with registry.getGui() pattern
  • PR #1705 — Introduces registry provider and manager context; directly complements this PR's registry integration at layout level
  • PR #1828 — Updates REGISTRY_URL constant in same file; related configuration change

Suggested labels

webapp, rust, enhancement

Suggested reviewers

  • hardyjosh
  • 0xgleb

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Out of Scope Changes check ❓ Inconclusive The PR includes some changes outside the core objective: settings backend modifications (documents field tracking, error surface improvements, remote token caching) and test removals (handleGuiInitialization tests) are infrastructure/support changes rather than direct registry SDK implementation. Clarify whether settings backend changes and test removals are necessary foundations for registry SDK integration or represent separate refactoring efforts that should be in a distinct PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Implement DotrainRegistry SDK in webapp' clearly and specifically describes the main change: integrating the DotrainRegistry SDK into the web application.
Linked Issues check ✅ Passed The PR addresses issue #2078 by obtaining RaindexClient from the registry SDK. The changes implement registry-based initialization of RaindexClient in the layout load and use registry.getAllOrderDetails() for order/deployment data retrieval, fulfilling the requirement to leverage registry logic for RaindexClient construction.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Comment @coderabbitai help to get the list of available commands and usage tips.

@findolor
Copy link
Collaborator Author

findolor commented Dec 1, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
packages/ui-components/src/__tests__/loadRegistryUrl.test.ts (1)

48-61: Add coverage for the validationResult.error branch

You’re covering the success path and both Error/non-Error rejection paths, but the new implementation also handles the case where DotrainRegistry.validate resolves with an error object (and uses .readableMsg). That branch isn’t exercised here.

Please add a test along the lines of:

(DotrainRegistry.validate as Mock).mockResolvedValueOnce({
  error: { readableMsg: 'Validation failed' }
});

await expect(loadRegistryUrl(testUrl, mockRegistryManager)).rejects.toThrow('Validation failed');
expect(mockRegistryManager.setRegistry).not.toHaveBeenCalled();
expect(window.location.reload).not.toHaveBeenCalled();

to lock in the intended behavior.

Also applies to: 63-77

packages/ui-components/src/lib/services/loadRegistryUrl.ts (1)

1-27: Ensure TS tooling and screenshot requirements are met

Since this is TS in packages/ui-components and affects frontend behavior, please ensure for this PR that:

  • nix develop -c npm run format -w @rainlanguage/ui-components
  • nix develop -c npm run lint -w @rainlanguage/ui-components
  • nix develop -c npm run check -w @rainlanguage/ui-components
  • nix develop -c npm run test -w @rainlanguage/ui-components

have been run and are green, and attach a screenshot of the built webapp showing the updated registry URL flow, per repo guidelines.

packages/webapp/src/routes/deploy/[orderName]/layout.test.ts (1)

62-72: Make the redirect test fail if load does not throw

The current try/catch pattern will pass even if load resolves successfully (no redirect), because there is no assertion in the success path. Restructure to assert that load rejects and that redirect was called:

-	it('should redirect if order name is not found in validOrders', async () => {
-		try {
-			await load({
-				params: { orderName: 'non-existent-order' },
-				parent: mockParent
-				// eslint-disable-next-line @typescript-eslint/no-explicit-any
-			} as any);
-		} catch {
-			expect(redirect).toHaveBeenCalledWith(307, '/deploy');
-		}
-	});
+	it('should redirect if order name is not found in validOrders', async () => {
+		await expect(
+			load({
+				params: { orderName: 'non-existent-order' },
+				parent: mockParent
+				// eslint-disable-next-line @typescript-eslint/no-explicit-any
+			} as any)
+		).rejects.toEqual(expect.anything());
+
+		expect(redirect).toHaveBeenCalledWith(307, '/deploy');
+	});

This ensures the test fails if load ever stops throwing.

crates/settings/src/unit_test.rs (1)

84-92: Functionally correct ScenarioCfg.documents init; consider reusing helper

Initializing documents with Arc::new(Vec::new()) is type‑correct and works. For consistency with the rest of the settings crate, you might prefer to call the shared default_documents() helper instead, but this is optional.

packages/ui-components/src/lib/components/deployment/OrderPage.svelte (1)

20-29: Non-OK response silently fails without feedback.

When response.ok is false (e.g., 404, 500), the function returns without setting an error or markdownContent. The user sees only the plain description without any indication that markdown fetch failed.

Consider setting an error message for non-OK responses:

 const fetchMarkdownContent = async (url: string) => {
 	try {
 		const response = await fetch(url);
 		if (response.ok) {
 			markdownContent = await response.text();
+		} else {
+			error = `Failed to fetch markdown (${response.status})`;
 		}
 	} catch {
 		error = `Failed to fetch markdown`;
 	}
 };

if (!errorMessage) {
try {
const registryResult = await DotrainRegistry.new(registryUrl);
console.log(registryResult);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove debug logging before merge.

This console.log statement appears to be debug code that should be removed from production.

-			console.log(registryResult);
🤖 Prompt for AI Agents
In packages/webapp/src/routes/+layout.ts around line 51, there's a leftover
debug console.log(registryResult); statement; remove this console.log line (or
replace it with appropriate structured logging at debug level if persistent
logging is required) so no debug output is emitted in production.

Comment on lines 173 to 214
it('should return errorMessage if registry fails to load', async () => {
mockRegistryNew.mockRejectedValueOnce(new Error('Network error'));

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await load({ fetch: mockFetch } as any);
const result = await load({ url: new URL('http://localhost:3000') } as any);

expect(result).toHaveProperty('stores', null);
expect(result).toHaveProperty('errorMessage');
expect(result.errorMessage).toContain('Failed to get site config settings.');
expect(result.errorMessage).toContain('Error status: 404');
expect(result.errorMessage).toContain('Failed to load registry');
});

it('should return errorMessage if response.text() fails', async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
text: () => Promise.reject(new Error('Invalid YAML'))
it('should return errorMessage if RaindexClient fails to initialize', async () => {
const mockRegistry = { settings: vi.fn().mockReturnValue('settings') };
mockRegistryNew.mockResolvedValueOnce({
value: mockRegistry
});
mockRaindexClientNew.mockReturnValue({
error: { readableMsg: 'Malformed settings' }
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await load({ fetch: mockFetch } as any);

expect(result).toHaveProperty('stores', null);
expect(result).toHaveProperty('errorMessage');
expect(result.errorMessage).toContain('Failed to get site config settings.');
expect(result.errorMessage).toContain('Invalid YAML');
});

it('should handle fetch failure', async () => {
mockFetch.mockRejectedValueOnce(new Error('Network error'));

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await load({ fetch: mockFetch } as any);
const result = await load({ url: new URL('http://localhost:3000') } as any);

expect(result).toHaveProperty('stores', null);
expect(result).toHaveProperty('errorMessage');
expect(result.errorMessage).toContain('Failed to get site config settings.');
expect(result.errorMessage).toContain('Network error');
expect(result.errorMessage).toContain('Malformed settings');
});

it('should handle empty or malformed settings YAML', async () => {
(RaindexClient.new as Mock).mockReturnValue({
value: undefined,
error: {
msg: 'Malformed settings',
readableMsg: 'Malformed settings'
}
it('should initialize when registry and RaindexClient succeed', async () => {
const mockRegistry = { settings: 'settings' };
mockRegistryNew.mockResolvedValueOnce({
value: mockRegistry
});
mockFetch.mockResolvedValueOnce({
ok: true,
text: () => Promise.resolve('malformed')
mockRaindexClientNew.mockReturnValue({
value: { client: true }
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await load({ fetch: mockFetch } as any);
const result = await load({ url: new URL('http://localhost:3000') } as any);

expect(result).toHaveProperty('stores', null);
expect(result).toHaveProperty('errorMessage');
expect(result.errorMessage).toContain('Malformed settings');
expect(result.errorMessage).toContain('Malformed settings');
expect(result.errorMessage).toBeUndefined();
expect(result.stores).not.toBeNull();
expect(result.registry).toEqual(mockRegistry);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding test coverage for local database initialization failure.

The tests cover registry failure and RaindexClient failure, but there's no test for the SQLiteWasmDatabase.new failure path. Adding this would ensure complete error handling coverage.

Example test case to add:

it('should return errorMessage if local database fails to initialize', async () => {
	const mockRegistry = { settings: 'settings' };
	mockRegistryNew.mockResolvedValueOnce({
		value: mockRegistry
	});
	mockRaindexClientNew.mockReturnValue({
		value: { client: true }
	});
	mockLocalDbNew.mockReturnValue({
		error: { readableMsg: 'Database init failed' }
	});

	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	const result = await load({ url: new URL('http://localhost:3000') } as any);

	expect(result).toHaveProperty('stores', null);
	expect(result.errorMessage).toContain('Error initializing local database');
});
🤖 Prompt for AI Agents
In packages/webapp/src/routes/+layout.ts around lines 173 to 214, add a test
that covers the SQLiteWasmDatabase.new failure path: mock the registry and
RaindexClient to succeed (as done in existing tests), set mockLocalDbNew to
return an error object with readableMsg 'Database init failed', call load({ url:
new URL('http://localhost:3000') } as any), and assert that result.stores is
null (or hasProperty 'stores', null) and result.errorMessage contains 'Error
initializing local database' (or contains the readableMsg), following the same
test structure and eslint-disable comment used in the other tests.

Comment on lines 29 to 33
if (!deployment || !registry || !orderName) {
setTimeout(() => {
goto('/deploy');
}, 5000);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

setTimeout runs outside lifecycle hook, may execute during SSR.

The redirect logic with setTimeout executes at module evaluation time (not inside onMount), which could cause issues during server-side rendering where goto may not behave as expected.

Consider moving this logic inside onMount to ensure it only runs client-side:

+	onMount(async () => {
+		if (!deployment || !registry || !orderName) {
+			setTimeout(() => {
+				goto('/deploy');
+			}, 5000);
+			return;
+		}
+
-	if (!deployment || !registry || !orderName) {
-		setTimeout(() => {
-			goto('/deploy');
-		}, 5000);
-	}
-
-	onMount(async () => {
-		if (!deployment || !registry || !orderName) return;
-
		const serializedState = stateFromUrl || undefined;
		// ... rest of onMount
	});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!deployment || !registry || !orderName) {
setTimeout(() => {
goto('/deploy');
}, 5000);
}
onMount(async () => {
if (!deployment || !registry || !orderName) {
setTimeout(() => {
goto('/deploy');
}, 5000);
return;
}
const serializedState = stateFromUrl || undefined;
// ... rest of onMount
});
🤖 Prompt for AI Agents
In packages/webapp/src/routes/deploy/[orderName]/[deploymentKey]/+page.svelte
around lines 29-33 the setTimeout redirect runs at module evaluation time which
can execute during SSR; move the redirect logic into a client-only lifecycle
hook: wrap the existence check and setTimeout/goto call inside onMount so it
only runs in the browser, and import onMount from 'svelte' if not already
present.

Comment on lines 69 to 82
it('should redirect if order details are not found in validOrders', async () => {
mockParent.mockResolvedValue({
registryDotrains: [{ name: 'incomplete-order', dotrain: 'https://incomplete.example.com' }],
validOrders: [
{ name: 'other-order', details: { name: 'Other', description: '', config: {} } }
]
],
invalidOrders: [],
registry: {
getDeploymentDetails: vi.fn().mockReturnValue({ value: mockDeployments })
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix mismatch between test name and fixture for “missing details” case

This test claims to cover “order details are not found in validOrders”, but the fixture has no validOrders entry for 'incomplete-order', so it effectively duplicates the “order name not found” scenario.

If the intention is to simulate an order entry with missing details, consider aligning the fixture with the param, e.g.:

-		mockParent.mockResolvedValue({
-			validOrders: [
-				{ name: 'other-order', details: { name: 'Other', description: '', config: {} } }
-			],
-			invalidOrders: [],
-			registry: {
-				getDeploymentDetails: vi.fn().mockReturnValue({ value: mockDeployments })
-			}
-		});
+		mockParent.mockResolvedValue({
+			validOrders: [
+				{
+					name: 'incomplete-order',
+					// @ts-expect-error simulate missing details shape
+					details: null
+				}
+			],
+			invalidOrders: [],
+			registry: {
+				getDeploymentDetails: vi.fn().mockReturnValue({ value: mockDeployments })
+			}
+		});

This way the test actually exercises the “no details for an otherwise valid order name” branch.

🤖 Prompt for AI Agents
In packages/webapp/src/routes/deploy/[orderName]/layout.test.ts around lines 74
to 82, the test name says it should cover the case where an order exists in
validOrders but its details are missing, yet the fixture instead omits the order
entirely (duplicating the “order name not found” case); update the mockParent
fixture to include a validOrders entry for 'incomplete-order' (the test param)
with its details property missing or explicitly null/undefined so the test
actually exercises the "order present but details missing" branch, and ensure
other parts of the fixture (invalidOrders/registry) remain consistent with that
scenario.

Comment on lines 16 to 27
export const load: LayoutLoad<LoadResult> = async ({ parent }) => {
const parentData = await parent();
const registry = (parentData as { registry?: DotrainRegistry | null }).registry ?? null;

if (!registry) {
return {
validOrders: [],
invalidOrders: [],
registry,
error: 'Registry not loaded'
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Parent data type assertion could be more explicit.

The type assertion (parentData as { registry?: DotrainRegistry | null }) works but is somewhat fragile. Consider defining a proper parent type or using a type guard for better type safety.

+type RootLayoutData = {
+	registry?: DotrainRegistry | null;
+};

 export const load: LayoutLoad<LoadResult> = async ({ parent }) => {
 	const parentData = await parent();
-	const registry = (parentData as { registry?: DotrainRegistry | null }).registry ?? null;
+	const registry = (parentData as RootLayoutData).registry ?? null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const load: LayoutLoad<LoadResult> = async ({ parent }) => {
const parentData = await parent();
const registry = (parentData as { registry?: DotrainRegistry | null }).registry ?? null;
if (!registry) {
return {
validOrders: [],
invalidOrders: [],
registry,
error: 'Registry not loaded'
};
}
type RootLayoutData = {
registry?: DotrainRegistry | null;
};
export const load: LayoutLoad<LoadResult> = async ({ parent }) => {
const parentData = await parent();
const registry = (parentData as RootLayoutData).registry ?? null;
if (!registry) {
return {
validOrders: [],
invalidOrders: [],
registry,
error: 'Registry not loaded'
};
}
🤖 Prompt for AI Agents
In packages/webapp/src/routes/deploy/+layout.ts around lines 16–27, the current
cast "(parentData as { registry?: DotrainRegistry | null })" is fragile; define
an explicit parent-data interface (e.g. interface ParentData { registry?:
DotrainRegistry | null }) and use it when calling parent() (or pass the generic
to LayoutLoad) so parentData is strongly typed, or implement a small type guard
function isParentData(x): x is ParentData and use that to narrow parentData
before accessing registry; replace the inline assertion with the typed variable
or guard to ensure type safety.

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.

3 participants