Skip to content

notify extension dev server of app assets updates#7227

Merged
isaacroldan merged 2 commits intomainfrom
04-09-notify_extension_dev_server_of_app_assets_updates
Apr 14, 2026
Merged

notify extension dev server of app assets updates#7227
isaacroldan merged 2 commits intomainfrom
04-09-notify_extension_dev_server_of_app_assets_updates

Conversation

@isaacroldan
Copy link
Copy Markdown
Contributor

@isaacroldan isaacroldan commented Apr 9, 2026

WHY are these changes introduced?

During local development, the extension dev server needs to serve app-level assets (e.g., admin static_root files) and expose app configuration like allowed_domains so the dev console and host can
properly load and refresh them.

WHAT is this pull request doing?

  • Serves app assets through a new /extensions/assets/:assetKey/ route on the dev server, with path traversal protection
  • Adds allowed_domains and assets (URL + timestamp) to the extensions payload so connected clients know about them
  • Bumps asset timestamps and updates allowed_domains in the payload when the admin config changes during dev, triggering a websocket update to clients
  • Adds allowed_domains to the admin extension schema and transformRemoteToLocal
  • Passes all realExtensions (not just previewable ones) through to the dev server so config-only extensions like admin are visible for extracting app-level config
  • Centralizes all admin config extraction in store.ts via a getAdminConfig() helper
  • Changes manifest generation to overwrite existing manifest.json instead of throwing
  • Watches realExtensions in the file watcher so config extensions with custom watch paths are included
  • Adds workaround to always include admin in dev session manifests (incompatible with inheritedUids in Core)

How to test your changes?

  1. Create an app with an admin extension that has static_root and allowed_domains configured
  2. Run shopify app dev
  3. Verify assets are served at the generated asset URLs
  4. Modify assets or allowed_domains in the config and confirm the payload updates via websocket

Copy link
Copy Markdown
Contributor Author

isaacroldan commented Apr 9, 2026

@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 2670bff to 7fd0331 Compare April 9, 2026 10:25
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch 2 times, most recently from 1e0e9ea to 7efd3f7 Compare April 9, 2026 13:12
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch 2 times, most recently from 73363b9 to 8e75a20 Compare April 9, 2026 13:24
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from 7efd3f7 to 85f5b0f Compare April 9, 2026 13:24
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 8e75a20 to 52ef686 Compare April 9, 2026 13:26
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from 85f5b0f to 4c6daca Compare April 9, 2026 13:26
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 52ef686 to 9cd7adc Compare April 9, 2026 13:29
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from 4c6daca to 1ba2dd9 Compare April 9, 2026 13:29
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 9cd7adc to dc2a701 Compare April 9, 2026 13:35
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from 1ba2dd9 to 5dfacdb Compare April 9, 2026 13:35
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from dc2a701 to c6ca3d1 Compare April 9, 2026 13:38
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from 82d0865 to 8c27933 Compare April 9, 2026 14:13
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch 2 times, most recently from 665154d to a1b4321 Compare April 9, 2026 14:19
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from 8c27933 to fc760cc Compare April 9, 2026 14:19
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from a1b4321 to fa4c046 Compare April 9, 2026 14:28
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch 2 times, most recently from 3383e69 to d1271b9 Compare April 9, 2026 14:32
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch 5 times, most recently from b655072 to 3dc00e6 Compare April 9, 2026 16:04
@elanalynn elanalynn mentioned this pull request Apr 9, 2026
4 tasks
@github-actions
Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

We found no new type declarations in this PR

Existing type declarations

packages/cli-kit/dist/private/node/ui.d.ts
 import { Logger, LogLevel } from '../../public/node/output.js';
-import React from 'react';
 import { Key, RenderOptions } from 'ink';
 import { EventEmitter } from 'events';
-/**
- * Signal that the current Ink tree is done. Must be called within an
- * InkLifecycleRoot — throws if the provider is missing so lifecycle
- * bugs surface immediately instead of silently hanging.
- */
-export declare function useComplete(): (error?: Error) => void;
-/**
- * Root wrapper for Ink trees. Owns the single `exit()` call site — children
- * signal completion via `useComplete()`, which sets state here. The `useEffect`
- * fires post-render, guaranteeing all batched state updates have been flushed
- * before the tree is torn down.
- */
-export declare function InkLifecycleRoot({ children }: {
-    children: React.ReactNode;
-}): React.JSX.Element;
 interface RenderOnceOptions {
     logLevel?: LogLevel;
     logger?: Logger;
     renderOptions?: RenderOptions;
 }
 export declare function renderOnce(element: JSX.Element, { logLevel, renderOptions }: RenderOnceOptions): string | undefined;
-export declare function render(element: JSX.Element, options?: RenderOptions): Promise<void>;
+export declare function render(element: JSX.Element, options?: RenderOptions): Promise<unknown>;
 export declare class Stdout extends EventEmitter {
     columns: number;
     rows: number;
     readonly frames: string[];
     private _lastFrame?;
     constructor(options: {
         columns?: number;
         rows?: number;
     });
     write: (frame: string) => void;
     lastFrame: () => string | undefined;
 }
 export declare function handleCtrlC(input: string, key: Key, exit?: () => void): void;
 export {};
packages/cli-kit/dist/public/node/ui.d.ts
@@ -34,7 +34,7 @@ export interface RenderConcurrentOptions extends PartialBy<ConcurrentOutputProps
  * 00:00:00 │ frontend │ third frontend message
  *
  */
-export declare function renderConcurrent({ renderOptions, ...props }: RenderConcurrentOptions): Promise<void>;
+export declare function renderConcurrent({ renderOptions, ...props }: RenderConcurrentOptions): Promise<unknown>;
 export type AlertCustomSection = CustomSection;
 export type RenderAlertOptions = Omit<AlertOptions, 'type'>;
 /**

@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 535fde3 to 5399272 Compare April 10, 2026 15:40
@isaacroldan isaacroldan force-pushed the 04-08-extract_custom_watch_paths_to_specifications branch from d1271b9 to 06b34f4 Compare April 10, 2026 15:40
@isaacroldan isaacroldan marked this pull request as ready for review April 10, 2026 15:42
@isaacroldan isaacroldan requested a review from a team as a code owner April 10, 2026 15:42
Base automatically changed from 04-08-extract_custom_watch_paths_to_specifications to main April 10, 2026 16:59
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 5399272 to 42083ba Compare April 10, 2026 17:14
Copilot AI review requested due to automatic review settings April 13, 2026 15:57
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 42083ba to c77befd Compare April 13, 2026 15:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the local UI extensions development server to support serving app-level assets (notably admin static_root) and to propagate related metadata (URLs + timestamps) through the extensions payload so clients can fetch and refresh those assets during development.

Changes:

  • Adds app.allowed_domains and app.assets metadata into the extensions payload and shared type definitions.
  • Introduces an HTTP middleware + route (/extensions/assets/:assetKey/...) for serving app assets from configured directories.
  • Expands dev file watching and build/include-assets behavior (watch realExtensions; overwrite generated manifest.json; admin spec updates).

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/ui-extensions-server-kit/src/types.ts Extends App payload types with allowed_domains and assets.
packages/app/src/cli/services/dev/processes/setup-dev-processes.ts Passes realExtensions into previewable extension process setup.
packages/app/src/cli/services/dev/processes/dev-session/dev-session.ts Workaround to always include admin in update manifests.
packages/app/src/cli/services/dev/extension/server/middlewares.ts Adds middleware to serve app assets by key/path.
packages/app/src/cli/services/dev/extension/server.ts Registers the new app-assets route when asset directories exist.
packages/app/src/cli/services/dev/extension/payload/store.ts Adds admin-derived app config/assets to payload and tracks asset directories/timestamps.
packages/app/src/cli/services/dev/extension/payload/store.test.ts Adjusts store option mocks for new constructor usage.
packages/app/src/cli/services/dev/extension/payload/models.ts Updates payload interface with new app fields.
packages/app/src/cli/services/dev/extension.ts Triggers admin config/timestamp updates on extension events; refactors server setup call.
packages/app/src/cli/services/dev/extension.test.ts Updates mocks/assertions for new payload store methods.
packages/app/src/cli/services/dev/app-events/file-watcher.ts Watches realExtensions files (including config extensions).
packages/app/src/cli/services/build/steps/include-assets/generate-manifest.ts Changes manifest generation to overwrite existing manifest.json.
packages/app/src/cli/services/build/steps/include-assets-step.test.ts Updates tests to expect manifest overwrite behavior.
packages/app/src/cli/models/extensions/specifications/admin.ts Adds allowed_domains to schema; exports AdminConfigType; watches static_root files.
packages/app/src/cli/models/extensions/specification.ts No functional change (formatting).
packages/app/src/cli/models/extensions/extension-instance.ts Uses isAppConfigExtension when deciding default dev-session watch behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch 3 times, most recently from 9dd6439 to 8cb333a Compare April 13, 2026 16:43
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 8cb333a to 06b860d Compare April 13, 2026 18:28
url: string
mobileUrl: string
title: string
allowed_domains?: string[]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we make this allowedDomains so it's consistent with the other fields which are camel cased?

this.emitUpdate([extension.devUUID])
}

updateAdminConfigFromExtensionEvents(extensionEvents: ExtensionEvent[]) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we considering passing the extension type as an array of types parameter in case there are in the future other app configs that need extension event?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This a very specific and special case and I don't expect something similar to happen again.
UI Extensions are already handled in a generic way, if at any point appears other extension with custom behavoiur we can see how to generalize it.

@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 06b860d to 810b2e3 Compare April 14, 2026 10:41
…Config

Co-authored-by: Claude Code <claude-code@anthropic.com>
@isaacroldan isaacroldan force-pushed the 04-09-notify_extension_dev_server_of_app_assets_updates branch from 810b2e3 to b93e0fe Compare April 14, 2026 10:48
@isaacroldan isaacroldan added this pull request to the merge queue Apr 14, 2026
Merged via the queue into main with commit f264d10 Apr 14, 2026
25 checks passed
@isaacroldan isaacroldan deleted the 04-09-notify_extension_dev_server_of_app_assets_updates branch April 14, 2026 11:13
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.

4 participants