feat(app-dev): sync error hints, flatEntity labels, dev-mode summary UI, and docs (#21252)

Split out of #21240 — all remaining app-dev improvements. Stacked on
#21251 (review/merge that first).

- Actionable recovery hints on failed syncs; unified diff renderer;
`--dry-run` guard.
- Return `flatEntity` on update/delete sync actions and unify the diff
label.
- Summarize the dev-mode entity list unless `--verbose`.
- Docs: syncing & recovery guide + dry-run + open-an-issue prompt.
- Live execution mode for synced logic functions; clearer manifest
warnings.

<img width="1018" height="700" alt="image"
src="https://github.com/user-attachments/assets/5e9ce19e-0f1d-4f99-8524-4e118bde932b"
/>
This commit is contained in:
martmull
2026-06-08 17:43:28 +02:00
committed by GitHub
parent 13e8e26d1c
commit 77d1e8ced6
34 changed files with 716 additions and 292 deletions
@@ -52,10 +52,7 @@ export class ApplicationSyncService {
hasSchemaMetadataChanged: boolean;
}> {
const ownerFlatApplication: FlatApplication = dryRun
? await this.applicationService.findOneApplicationOrThrow({
universalIdentifier: manifest.application.universalIdentifier,
workspaceId,
})
? await this.findInstalledApplicationOrThrow({ workspaceId, manifest })
: await this.syncApplication({
workspaceId,
manifest,
@@ -77,6 +74,30 @@ export class ApplicationSyncService {
return syncResult;
}
private async findInstalledApplicationOrThrow({
workspaceId,
manifest,
}: {
workspaceId: string;
manifest: Manifest;
}): Promise<ApplicationEntity> {
const application = await this.applicationService.findByUniversalIdentifier(
{
universalIdentifier: manifest.application.universalIdentifier,
workspaceId,
},
);
if (!application) {
throw new ApplicationException(
`Application "${manifest.application.universalIdentifier}" is not installed in workspace "${workspaceId}". Install it first.`,
ApplicationExceptionCode.APP_NOT_INSTALLED,
);
}
return application;
}
// Registers the application + only the pre-install logic function in
// workspace metadata so the pre-install hook can resolve and execute it
// before the main synchronizeFromManifest runs the full migrations.
@@ -40,7 +40,7 @@ export const fromLogicFunctionManifestToUniversalFlatLogicFunction = ({
workflowActionTriggerSettings:
logicFunctionManifest.workflowActionTriggerSettings ?? null,
isBuildUpToDate: true,
executionMode: LogicFunctionExecutionMode.PREBUILT,
executionMode: LogicFunctionExecutionMode.LIVE,
createdAt: now,
updatedAt: now,
deletedAt: null,