@flowdular/sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/.ai/skills/test-hardening/SKILL.md +1 -1
  2. package/README.md +69 -12
  3. package/assets/flowdular-banner.png +0 -0
  4. package/modules/agents/package.json +1 -1
  5. package/modules/auth/package.json +1 -1
  6. package/modules/auth/src/client/AuthenticationCore.tsrx +3 -1
  7. package/modules/auth/src/server/endpoints.ts +3 -1
  8. package/modules/auth/src/server/runtime.ts +4 -0
  9. package/modules/automations/package.json +1 -1
  10. package/modules/automations-workflows-integration/package.json +1 -1
  11. package/modules/profile/package.json +1 -1
  12. package/modules/sandbox/package.json +1 -1
  13. package/modules/system/package.json +1 -1
  14. package/modules/users/package.json +1 -1
  15. package/modules/workflows/package.json +1 -1
  16. package/package.json +5 -13
  17. package/packages/ai-provider/package.json +1 -1
  18. package/packages/cli-protocol/package.json +1 -1
  19. package/packages/client/package.json +1 -1
  20. package/packages/client/src/routing.ts +39 -2
  21. package/packages/client/src/shell/BrandMark.tsrx +5 -1
  22. package/packages/client/src/shell/navigation.ts +3 -1
  23. package/packages/client/src/state.ts +6 -2
  24. package/packages/contracts/package.json +1 -1
  25. package/packages/contracts/schemas/project.schema.json +16 -42
  26. package/packages/database/package.json +1 -1
  27. package/packages/database-pglite/package.json +1 -1
  28. package/packages/database-testing/package.json +1 -1
  29. package/packages/dev-console/package.json +1 -1
  30. package/packages/harness/package.json +1 -1
  31. package/packages/kernel/package.json +1 -1
  32. package/packages/server/package.json +1 -1
  33. package/packages/server/src/application-routes.ts +80 -8
  34. package/packages/server/src/index.ts +4 -1
  35. package/packages/server/src/web-html.ts +9 -5
  36. package/packages/server/src/web.ts +59 -7
  37. package/packages/ui/package.json +1 -1
  38. package/packages/coding-agent/package.json +0 -44
  39. package/packages/coding-agent/src/drivers/byok.ts +0 -322
  40. package/packages/coding-agent/src/drivers/claude-code.ts +0 -290
  41. package/packages/coding-agent/src/drivers/codex.ts +0 -281
  42. package/packages/coding-agent/src/index.ts +0 -56
  43. package/packages/coding-agent/src/registry.ts +0 -119
  44. package/packages/coding-agent/src/roles/contract.ts +0 -60
  45. package/packages/coding-agent/src/roles/defaults.ts +0 -134
  46. package/packages/coding-agent/src/roles/handoff.ts +0 -41
  47. package/packages/coding-agent/src/roles/registry.ts +0 -156
  48. package/packages/coding-agent/src/roles/skills.ts +0 -72
  49. package/packages/coding-agent/src/roles/sync.ts +0 -88
  50. package/packages/coding-agent/src/types.ts +0 -102
  51. package/packages/coding-agent/src/workspace.ts +0 -275
  52. package/packages/sandbox/README.md +0 -691
  53. package/packages/sandbox/bin/flowdular-sandbox.mjs +0 -393
  54. package/packages/sandbox/dist/client/assets/App-ClMOrpyg.js +0 -11
  55. package/packages/sandbox/dist/client/assets/PreviewHost-BHiHrfbQ.js +0 -1
  56. package/packages/sandbox/dist/client/assets/auto-buGEq6de.js +0 -3
  57. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  58. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  59. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
  60. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
  61. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  62. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  63. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
  64. package/packages/sandbox/dist/client/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
  65. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  66. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  67. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  68. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  69. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  70. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  71. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
  72. package/packages/sandbox/dist/client/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
  73. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  74. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  75. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
  76. package/packages/sandbox/dist/client/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
  77. package/packages/sandbox/dist/client/assets/ibm-plex-sans-cyrillic-ext-wght-normal-d45eAU9y.woff2 +0 -0
  78. package/packages/sandbox/dist/client/assets/ibm-plex-sans-cyrillic-wght-normal-BAAhND-U.woff2 +0 -0
  79. package/packages/sandbox/dist/client/assets/ibm-plex-sans-greek-wght-normal-CmyJS8uq.woff2 +0 -0
  80. package/packages/sandbox/dist/client/assets/ibm-plex-sans-latin-ext-wght-normal-CIII54If.woff2 +0 -0
  81. package/packages/sandbox/dist/client/assets/ibm-plex-sans-latin-wght-normal-IvpUvPa2.woff2 +0 -0
  82. package/packages/sandbox/dist/client/assets/ibm-plex-sans-vietnamese-wght-normal-Dg1JeJN0.woff2 +0 -0
  83. package/packages/sandbox/dist/client/assets/index-CvwhlQ87.js +0 -4
  84. package/packages/sandbox/dist/client/assets/styles-BPWaGf55.js +0 -3
  85. package/packages/sandbox/dist/client/assets/styles-Dx1_KOag.css +0 -1
  86. package/packages/sandbox/dist/client/favicon.svg +0 -1
  87. package/packages/sandbox/dist/server/assets/auto-CVGNYyb3.js +0 -12785
  88. package/packages/sandbox/dist/server/assets/chunk-DDJLRBDX-3OUNo51g.js +0 -4125
  89. package/packages/sandbox/dist/server/assets/nodefs-DVSI7kG0.js +0 -24
  90. package/packages/sandbox/dist/server/assets/opfs-ahp-D56iokt1.js +0 -388
  91. package/packages/sandbox/dist/server/assets/token-Bvaq7Anz.js +0 -55
  92. package/packages/sandbox/dist/server/assets/token-util-BqSvdIPQ.js +0 -3
  93. package/packages/sandbox/dist/server/assets/token-util-CktFFT4z.js +0 -494
  94. package/packages/sandbox/dist/server/entry.js +0 -91671
  95. package/packages/sandbox/dist/server/favicon.svg +0 -1
  96. package/packages/sandbox/dist/server/index.html +0 -161
  97. package/packages/sandbox/index.html +0 -159
  98. package/packages/sandbox/octane.config.ts +0 -36
  99. package/packages/sandbox/package.json +0 -83
  100. package/packages/sandbox/public/favicon.svg +0 -1
  101. package/packages/sandbox/public/og.png +0 -0
  102. package/packages/sandbox/src/App.tsrx +0 -924
  103. package/packages/sandbox/src/client/ApprovalHandoff.tsrx +0 -39
  104. package/packages/sandbox/src/client/ChatPane.tsrx +0 -694
  105. package/packages/sandbox/src/client/ConnectView.tsrx +0 -86
  106. package/packages/sandbox/src/client/DiffPane.tsrx +0 -150
  107. package/packages/sandbox/src/client/EjectModal.tsrx +0 -571
  108. package/packages/sandbox/src/client/GateResults.tsrx +0 -60
  109. package/packages/sandbox/src/client/GitHubSettingsModal.tsrx +0 -219
  110. package/packages/sandbox/src/client/NewSessionForm.tsrx +0 -214
  111. package/packages/sandbox/src/client/SessionBar.tsrx +0 -151
  112. package/packages/sandbox/src/client/SessionPicker.tsrx +0 -472
  113. package/packages/sandbox/src/client/SpecEditor.tsrx +0 -109
  114. package/packages/sandbox/src/client/SpecReviewCard.tsrx +0 -321
  115. package/packages/sandbox/src/client/WorkCard.tsrx +0 -128
  116. package/packages/sandbox/src/client/WorkbenchModal.tsrx +0 -161
  117. package/packages/sandbox/src/client/WorkspaceMenu.tsrx +0 -100
  118. package/packages/sandbox/src/client/api.ts +0 -797
  119. package/packages/sandbox/src/client/attachments.ts +0 -73
  120. package/packages/sandbox/src/client/dashboard.ts +0 -46
  121. package/packages/sandbox/src/client/github-settings.ts +0 -48
  122. package/packages/sandbox/src/client/highlight.ts +0 -105
  123. package/packages/sandbox/src/client/i18n.ts +0 -32
  124. package/packages/sandbox/src/client/locales/en.json +0 -466
  125. package/packages/sandbox/src/client/locales/pl.json +0 -466
  126. package/packages/sandbox/src/client/session-labels.ts +0 -77
  127. package/packages/sandbox/src/client/state.ts +0 -108
  128. package/packages/sandbox/src/index.ts +0 -10
  129. package/packages/sandbox/src/preview/PreviewHost.tsrx +0 -373
  130. package/packages/sandbox/src/preview/load-module.ts +0 -16
  131. package/packages/sandbox/src/server/attachments.ts +0 -308
  132. package/packages/sandbox/src/server/auto-review.ts +0 -181
  133. package/packages/sandbox/src/server/checkpoints.ts +0 -90
  134. package/packages/sandbox/src/server/config.ts +0 -460
  135. package/packages/sandbox/src/server/dashboard.ts +0 -245
  136. package/packages/sandbox/src/server/delivery/configuration.ts +0 -193
  137. package/packages/sandbox/src/server/delivery/git-pr.ts +0 -1473
  138. package/packages/sandbox/src/server/delivery/index.ts +0 -83
  139. package/packages/sandbox/src/server/delivery/local.ts +0 -151
  140. package/packages/sandbox/src/server/delivery/official-modules.ts +0 -516
  141. package/packages/sandbox/src/server/delivery/plan.ts +0 -218
  142. package/packages/sandbox/src/server/delivery/policies.ts +0 -239
  143. package/packages/sandbox/src/server/delivery/record.ts +0 -41
  144. package/packages/sandbox/src/server/delivery/steps.ts +0 -464
  145. package/packages/sandbox/src/server/delivery/types.ts +0 -158
  146. package/packages/sandbox/src/server/dependencies.ts +0 -88
  147. package/packages/sandbox/src/server/diff.ts +0 -230
  148. package/packages/sandbox/src/server/gates.ts +0 -388
  149. package/packages/sandbox/src/server/index.ts +0 -139
  150. package/packages/sandbox/src/server/path-guard.ts +0 -282
  151. package/packages/sandbox/src/server/planning.ts +0 -749
  152. package/packages/sandbox/src/server/platform-client.ts +0 -189
  153. package/packages/sandbox/src/server/preview-database-host.ts +0 -340
  154. package/packages/sandbox/src/server/preview-database-protocol.ts +0 -163
  155. package/packages/sandbox/src/server/preview-database-proxy.ts +0 -356
  156. package/packages/sandbox/src/server/preview-database.ts +0 -109
  157. package/packages/sandbox/src/server/preview-ipc.ts +0 -15
  158. package/packages/sandbox/src/server/preview-modules.ts +0 -83
  159. package/packages/sandbox/src/server/preview-revision.ts +0 -44
  160. package/packages/sandbox/src/server/preview-runtime.ts +0 -467
  161. package/packages/sandbox/src/server/preview-worker-manager.ts +0 -436
  162. package/packages/sandbox/src/server/preview-worker.ts +0 -168
  163. package/packages/sandbox/src/server/reference.ts +0 -251
  164. package/packages/sandbox/src/server/routes.ts +0 -2258
  165. package/packages/sandbox/src/server/runtime.ts +0 -188
  166. package/packages/sandbox/src/server/session-owner.ts +0 -23
  167. package/packages/sandbox/src/server/sessions.ts +0 -849
  168. package/packages/sandbox/src/server/spec.ts +0 -471
  169. package/packages/sandbox/src/server/turn-lifecycle.ts +0 -56
  170. package/packages/sandbox/src/server/turns.ts +0 -993
  171. package/packages/sandbox/src/server/workspace-install.ts +0 -266
  172. package/packages/sandbox/src/server/workspace-root.ts +0 -73
  173. package/packages/sandbox/src/styles.css +0 -1573
  174. package/packages/sandbox/vite.config.ts +0 -133
@@ -1,571 +0,0 @@
1
- import { Alert, Button, Icon, Tag } from '@flowdular/sdk/ui';
2
- import type {
3
- EjectPlanView,
4
- EjectStep,
5
- EjectSummary,
6
- EjectTargetId,
7
- } from './api.ts';
8
- import { activeLocale, t, useTranslation } from './i18n.ts';
9
- import {
10
- deliveryStepLabel,
11
- deliveryStepDetail,
12
- gateLabel,
13
- } from './session-labels.ts';
14
-
15
- export interface EjectModalProps {
16
- readonly plan: EjectPlanView;
17
- readonly steps: readonly EjectStep[];
18
- readonly summary: EjectSummary | null;
19
- readonly error: string;
20
- readonly running: boolean;
21
- readonly build: boolean;
22
- readonly onBuild: (build: boolean) => void;
23
- readonly onTarget: (target: EjectTargetId) => void;
24
- readonly onConfirm: () => void;
25
- readonly onClose: () => void;
26
- }
27
-
28
- const TARGET_LABELS: Readonly<Record<EjectTargetId, string>> = {
29
- workspace: 'target.workspace',
30
- 'git-pr': 'target.gitPr',
31
- 'official-modules': 'target.officialModules',
32
- };
33
-
34
- function stepIcon(status: EjectStep['status']): string {
35
- if (status === 'passed') return 'check';
36
- if (status === 'failed') return 'alert';
37
- if (status === 'note') return 'help';
38
- return 'refresh';
39
- }
40
-
41
- function others(plan: EjectPlanView): string {
42
- const count = plan.modules.length - 1;
43
- return count > 0 ? t('sandbox.eject.moreModules', { count }) : '';
44
- }
45
-
46
- function lead(plan: EjectPlanView): string {
47
- if (plan.target === 'official-modules') return t(
48
- 'sandbox.eject.lead.officialModules',
49
- );
50
- if (plan.git) {
51
- return t('sandbox.eject.lead.git', {
52
- count: plan.git.changedFiles,
53
- branch: plan.git.branch,
54
- base: `${plan.git.remote}/${plan.git.baseBranch}`,
55
- target: plan.git.pushTarget,
56
- others: others(plan),
57
- });
58
- }
59
- if (plan.modules.length > 1) {
60
- return t('sandbox.eject.lead.multi', {
61
- files: plan.changedFiles,
62
- modules: plan.modules.length,
63
- });
64
- }
65
- const parts = [
66
- t('sandbox.eject.detail.filesLand', {
67
- count: plan.files.length,
68
- path: plan.targetPath,
69
- }),
70
- ...(plan.overwrites.length > 0
71
- ? [
72
- t('sandbox.eject.detail.overwritten', {
73
- count: plan.overwrites.length,
74
- }),
75
- ]
76
- : []),
77
- ...(plan.removes.length > 0
78
- ? [t('sandbox.eject.detail.removed', { count: plan.removes.length })]
79
- : []),
80
- ];
81
- return `${parts.join(', ')}${others(plan)}.`;
82
- }
83
-
84
- /* What one module of the delivery changes, in the same words the single-module
85
- lead uses. */
86
- function moduleDetail(module: EjectPlanView['modules'][number]): string {
87
- return [
88
- t('sandbox.eject.detail.files', { count: module.files.length }),
89
- ...(module.overwrites.length > 0
90
- ? [
91
- t('sandbox.eject.detail.overwritten', {
92
- count: module.overwrites.length,
93
- }),
94
- ]
95
- : []),
96
- ...(module.removes.length > 0
97
- ? [t('sandbox.eject.detail.removed', { count: module.removes.length })]
98
- : []),
99
- ...(module.newPackages.length > 0
100
- ? [
101
- t('sandbox.eject.detail.packages', {
102
- packages: module.newPackages.join(', '),
103
- }),
104
- ]
105
- : []),
106
- ...(module.enable ? [t('sandbox.eject.detail.enable')] : []),
107
- ].join(', ');
108
- }
109
-
110
- function explanation(plan: EjectPlanView): string {
111
- if (plan.target === 'official-modules') return t(
112
- 'sandbox.eject.explanation.officialModules',
113
- );
114
- if (plan.git) {
115
- return t('sandbox.eject.explanation.git');
116
- }
117
- return plan.modules.some((module) => module.enable)
118
- ? t('sandbox.eject.explanation.enable', { count: plan.modules.length })
119
- : t('sandbox.eject.explanation.copy', { count: plan.modules.length });
120
- }
121
-
122
- function totalRemoves(plan: EjectPlanView): number {
123
- return plan.modules.reduce(
124
- (total, module) => total + module.removes.length,
125
- 0,
126
- );
127
- }
128
-
129
- function newPackagesOf(plan: EjectPlanView): readonly string[] {
130
- return [
131
- ...new Set(plan.modules.flatMap((module) => module.newPackages)),
132
- ].sort();
133
- }
134
-
135
- /* What landed, named: one module by its id, several by their ids. */
136
- function delivered(summary: EjectSummary): string {
137
- return `${summary.modules.join(', ')} ${t(
138
- 'sandbox.eject.deliveredVerb.' +
139
- (summary.modules.length === 1 ? 'one' : 'other'),
140
- )}`;
141
- }
142
-
143
- function deliveredAt(at: number): string {
144
- return new Date(at).toLocaleString(activeLocale());
145
- }
146
-
147
- /* Eject is a delivery, so it gets its own screen: what will land, every step
148
- while it lands, and a plain confirmation when it has. */
149
- export function EjectModal(props: EjectModalProps) @{
150
- const { t } = useTranslation();
151
- const phase =
152
- props.summary
153
- ? 'done'
154
- : props.error
155
- ? 'failed'
156
- : props.running
157
- ? 'running'
158
- : 'plan';
159
- const git = props.plan.git;
160
- const official = props.plan.target === 'official-modules';
161
- const unavailable = props.plan.availableTargets.filter(
162
- (target) => !target.available,
163
- );
164
- const blocked = git ? !git.guardrails.ok : false;
165
-
166
- <div class="workbench eject" role="dialog" aria-modal="true">
167
- <div class="eject__panel">
168
- <header class="eject__head">
169
- <span class="eject__title">
170
- @if (phase === 'done') {
171
- <Icon name="check" size={18} />
172
- } @else {
173
- <Icon name="download" size={18} />
174
- }
175
- {phase === 'done'
176
- ? t('sandbox.eject.delivered')
177
- : props.plan.modules.length === 1
178
- ? t('sandbox.eject.title.one', { module: props.plan.moduleId })
179
- : t('sandbox.eject.title.other', {
180
- count: props.plan.modules.length,
181
- })}
182
- </span>
183
- <span class="sandbox__spacer"></span>
184
- <Tag mono>
185
- {git
186
- ? git.branch
187
- : props.plan.modules.length === 1
188
- ? props.plan.targetPath
189
- : t('sandbox.session.modules', {
190
- count: props.plan.modules.length,
191
- })}
192
- </Tag>
193
- </header>
194
-
195
- <div class="eject__body">
196
- @if (phase === 'plan') {
197
- <div class="eject__summary">
198
- @if (props.plan.availableTargets.length > 1) {
199
- <>
200
- <div
201
- class="ui-toolbar"
202
- role="radiogroup"
203
- aria-label={t('sandbox.eject.target.label')}
204
- >
205
- @for (const target of props.plan.availableTargets; key target.id) {
206
- <Button
207
- size="sm"
208
- variant={target.id === props.plan.target
209
- ? 'primary'
210
- : 'secondary'}
211
- disabled={!target.available}
212
- onClick={() => props.onTarget(target.id)}
213
- >{t('sandbox.eject.' + TARGET_LABELS[target.id])}</Button>
214
- }
215
- </div>
216
- @for (const target of unavailable; key target.id) {
217
- <span class="ui-help">{t('sandbox.eject.target.unavailable', {
218
- target: t('sandbox.eject.' + TARGET_LABELS[target.id]),
219
- reason: target.reason ?? t('sandbox.eject.unknownReason'),
220
- })}</span>
221
- }
222
- </>
223
- }
224
- <p class="eject__lead">{lead(props.plan)}</p>
225
- <p class="ui-help">{explanation(props.plan)}</p>
226
- <ul class="eject__steps">
227
- @for (const module of props.plan.modules; key module.id) {
228
- <li class="eject__step">
229
- <span class="eject__step-label">
230
- {module.id + ' (' + module.targetPath + ')'}
231
- </span>
232
- <span class="eject__step-detail">{moduleDetail(module)}</span>
233
- </li>
234
- }
235
- </ul>
236
- @if (git) {
237
- <>
238
- <ul class="eject__steps">
239
- <li class="eject__step">
240
- <span class="eject__step-label">{t(
241
- 'sandbox.eject.git.deliveryPath',
242
- )}</span>
243
- <span class="eject__step-detail">
244
- {git.deliveryMode === 'fork'
245
- ? t('sandbox.eject.git.fork', {
246
- target: git.pushTarget,
247
- suffix: git.forkRequired
248
- ? t('sandbox.eject.git.createdAfterConfirm')
249
- : '',
250
- })
251
- : t('sandbox.eject.git.directPush', {
252
- target: git.pushTarget,
253
- })}
254
- </span>
255
- </li>
256
- <li class="eject__step">
257
- <span class="eject__step-label">{t(
258
- 'sandbox.eject.git.branch',
259
- )}</span>
260
- <span class="eject__step-detail">
261
- {git.branch +
262
- (git.head !== git.branch ? ` (${git.head})` : '')}
263
- </span>
264
- </li>
265
- <li class="eject__step">
266
- <span class="eject__step-label">{t(
267
- 'sandbox.eject.git.base',
268
- )}</span>
269
- <span class="eject__step-detail">
270
- {git.remote + '/' + git.baseBranch}
271
- </span>
272
- </li>
273
- <li class="eject__step">
274
- <span class="eject__step-label">{t(
275
- 'sandbox.eject.git.changedFiles',
276
- )}</span>
277
- <span class="eject__step-detail">{t(
278
- 'sandbox.eject.git.changedFilesDetail',
279
- {
280
- changed: git.changedFiles,
281
- allowed: git.budget.maxChangedFiles,
282
- },
283
- )}</span>
284
- </li>
285
- @if (git.newDependencies.length > 0) {
286
- <li class="eject__step">
287
- <span class="eject__step-label">{t(
288
- 'sandbox.eject.git.newPackages',
289
- )}</span>
290
- <span class="eject__step-detail">{t(
291
- 'sandbox.eject.git.packagesDetail',
292
- {
293
- packages: git.newDependencies.join(', '),
294
- allowed: git.budget.maxNewDependencies,
295
- },
296
- )}</span>
297
- </li>
298
- }
299
- <li class="eject__step">
300
- <span class="eject__step-label">{t(
301
- 'sandbox.eject.git.owners',
302
- )}</span>
303
- <span class="eject__step-detail">
304
- {git.owners.length > 0
305
- ? git.owners.join(', ')
306
- : t('sandbox.eject.git.noOwners')}
307
- </span>
308
- </li>
309
- @if (git.reviewers.length > 0) {
310
- <li class="eject__step">
311
- <span class="eject__step-label">{t(
312
- 'sandbox.eject.git.reviewers',
313
- )}</span>
314
- <span class="eject__step-detail">{git.reviewers.join(
315
- ', ',
316
- )}</span>
317
- </li>
318
- }
319
- <li class="eject__step">
320
- <span class="eject__step-label">{t(
321
- 'sandbox.eject.git.pullRequest',
322
- )}</span>
323
- <span class="eject__step-detail">
324
- {git.provider === 'github'
325
- ? t('sandbox.eject.git.openedIn', {
326
- repository: git.repository ??
327
- t('sandbox.eject.git.configuredRepository'),
328
- })
329
- : git.providerNote}
330
- </span>
331
- </li>
332
- </ul>
333
- @if (blocked) {
334
- <Alert>{t('sandbox.eject.guardrails.blocked', {
335
- reasons: git.guardrails.reasons.join(' '),
336
- })}</Alert>
337
- } @else {
338
- <span class="ui-help">{t(
339
- 'sandbox.eject.guardrails.passed',
340
- )}</span>
341
- }
342
- </>
343
- }
344
- <ul class="eject__steps">
345
- @for (const gate of props.plan.gates; key gate) {
346
- <li class="eject__step">
347
- <span class="eject__step-dot"></span>
348
- {gateLabel(gate)}
349
- </li>
350
- }
351
- @if (git) {
352
- <li class="eject__step">
353
- <span class="eject__step-dot"></span>
354
- {t('sandbox.eject.step.fetch', {
355
- base: `${git.remote}/${git.baseBranch}`,
356
- branch: git.branch,
357
- })}
358
- </li>
359
- }
360
- <li class="eject__step">
361
- <span class="eject__step-dot"></span>
362
- {t('sandbox.eject.step.copy')}
363
- </li>
364
- @if (totalRemoves(props.plan) > 0) {
365
- <li class="eject__step">
366
- <span class="eject__step-dot"></span>
367
- {t('sandbox.eject.step.remove', {
368
- count: totalRemoves(props.plan),
369
- })}
370
- </li>
371
- }
372
- @for (const module of props.plan.modules.filter(
373
- (entry) => entry.enable,
374
- ); key module.id) {
375
- <li class="eject__step">
376
- <span class="eject__step-dot"></span>
377
- {t('sandbox.eject.step.enable', { module: module.id })}
378
- </li>
379
- }
380
- @if (!git && !official) {
381
- <li class="eject__step">
382
- <span class="eject__step-dot"></span>
383
- {t('sandbox.eject.step.grant')}
384
- </li>
385
- }
386
- <li class="eject__step">
387
- <span class="eject__step-dot"></span>
388
- {t('sandbox.eject.step.typecheck')}
389
- </li>
390
- @if (git) {
391
- <>
392
- <li class="eject__step">
393
- <span class="eject__step-dot"></span>
394
- {t('sandbox.eject.step.guardrails')}
395
- </li>
396
- <li class="eject__step">
397
- <span class="eject__step-dot"></span>
398
- {t('sandbox.eject.step.push', {
399
- branch: git.branch,
400
- remote: git.remote,
401
- })}
402
- </li>
403
- <li class="eject__step">
404
- <span class="eject__step-dot"></span>
405
- {git.provider === 'github'
406
- ? t('sandbox.eject.step.openPr')
407
- : t('sandbox.eject.step.compare')}
408
- </li>
409
- </>
410
- }
411
- @if (props.plan.restartRequired) {
412
- <li class="eject__step eject__step--note">
413
- <span class="eject__step-dot"></span>
414
- {props.plan.platformLocal
415
- ? t('sandbox.eject.step.restart')
416
- : t('sandbox.eject.step.deploy')}
417
- </li>
418
- }
419
- </ul>
420
- @if (newPackagesOf(props.plan).length > 0 && !git && !official) {
421
- <Alert tone="warning">{t('sandbox.eject.packagesWarning', {
422
- packages: newPackagesOf(props.plan).join(', '),
423
- })}</Alert>
424
- }
425
- @if (props.plan.previous) {
426
- <span class="ui-help">
427
- {t('sandbox.eject.previous', {
428
- date: deliveredAt(props.plan.previous.deliveredAt),
429
- branch: props.plan.previous.branch
430
- ? t('sandbox.eject.previousBranch', {
431
- branch: props.plan.previous.branch,
432
- })
433
- : '',
434
- })}
435
- @if (props.plan.previous.pullRequestUrl) {
436
- <a
437
- href={props.plan.previous.pullRequestUrl}
438
- target="_blank"
439
- rel="noreferrer"
440
- >{t('sandbox.eject.openPreviousPr')}</a>
441
- }
442
- </span>
443
- }
444
- @if (!git && !official) {
445
- <label class="ui-checkbox">
446
- <input
447
- type="checkbox"
448
- checked={props.build}
449
- onInput={(event) => props.onBuild(
450
- event.currentTarget.checked,
451
- )}
452
- />
453
- <span>{t('sandbox.eject.build')}</span>
454
- </label>
455
- }
456
- </div>
457
- } @else {
458
- <ul class="eject__steps">
459
- @for (const step of props.steps; key step.id) {
460
- <li class={['eject__step', 'eject__step--' + step.status]}>
461
- <span
462
- class={[
463
- 'eject__step-icon',
464
- step.status === 'running' && 'eject__step-icon--spin',
465
- ]}
466
- >
467
- <Icon name={stepIcon(step.status)} size={14} />
468
- </span>
469
- <span class="eject__step-label">{deliveryStepLabel(step)}</span>
470
- @if (step.detail) {
471
- <span class="eject__step-detail">{deliveryStepDetail(
472
- step,
473
- )}</span>
474
- }
475
- </li>
476
- }
477
- </ul>
478
- }
479
-
480
- @if (phase === 'done' && props.summary) {
481
- <div class="eject__done">
482
- <b>
483
- {props.summary.branch
484
- ? t('sandbox.eject.done.branch', {
485
- subject: delivered(props.summary),
486
- branch: props.summary.branch,
487
- })
488
- : t('sandbox.eject.done.workspace', {
489
- subject: delivered(props.summary),
490
- target: props.summary.modules.length === 1
491
- ? props.summary.targetPath
492
- : t('sandbox.eject.thisWorkspace'),
493
- })}
494
- </b>
495
- <span class="ui-help">{t('sandbox.eject.done.summary', {
496
- files: props.summary.files,
497
- removed: props.summary.removed > 0
498
- ? t('sandbox.eject.done.removed', {
499
- count: props.summary.removed,
500
- })
501
- : '',
502
- enabled: props.summary.enabled
503
- ? t('sandbox.eject.done.enabled')
504
- : '',
505
- })}</span>
506
- @if (props.summary.pullRequestUrl) {
507
- <a
508
- class="ui-btn ui-btn--secondary ui-btn--sm"
509
- href={props.summary.pullRequestUrl}
510
- target="_blank"
511
- rel="noreferrer"
512
- >{t('sandbox.eject.openPr')}</a>
513
- } @else if (props.summary.compareUrl) {
514
- <a
515
- class="ui-btn ui-btn--secondary ui-btn--sm"
516
- href={props.summary.compareUrl}
517
- target="_blank"
518
- rel="noreferrer"
519
- >{t('sandbox.eject.openCompare')}</a>
520
- } @else if (props.summary.branch) {
521
- <span class="ui-help">{t('sandbox.eject.branchPushed')}</span>
522
- }
523
- @if (props.summary.restartRequired) {
524
- <span class="ui-help">
525
- {props.summary.platformLocal
526
- ? t('sandbox.eject.restartNote')
527
- : t('sandbox.eject.deployNote')}
528
- </span>
529
- }
530
- </div>
531
- }
532
- @if (phase === 'failed') {
533
- <Alert>
534
- <span class="eject__error">{props.error}</span>
535
- </Alert>
536
- }
537
- </div>
538
-
539
- <footer class="eject__foot">
540
- @if (phase === 'plan') {
541
- <>
542
- <Button size="sm" variant="ghost" onClick={props.onClose}>{t(
543
- 'sandbox.common.cancel',
544
- )}</Button>
545
- <Button
546
- size="sm"
547
- variant="primary"
548
- disabled={blocked}
549
- onClick={props.onConfirm}
550
- >
551
- <Icon name="download" size={14} />
552
- {official
553
- ? t('sandbox.eject.target.officialModules')
554
- : git
555
- ? git.provider === 'github'
556
- ? t('sandbox.eject.confirmPr')
557
- : t('sandbox.eject.confirmBranch')
558
- : t('sandbox.eject.confirm')}
559
- </Button>
560
- </>
561
- } @else if (phase === 'running') {
562
- <span class="ui-help">{t('sandbox.eject.running')}</span>
563
- } @else {
564
- <Button size="sm" variant="primary" onClick={props.onClose}>{t(
565
- 'sandbox.common.close',
566
- )}</Button>
567
- }
568
- </footer>
569
- </div>
570
- </div>
571
- }
@@ -1,60 +0,0 @@
1
- import { Alert, Drawer, Tag } from '@flowdular/sdk/ui';
2
- import type { GateResult } from '../server/gates.ts';
3
- import { gateLabel } from './session-labels.ts';
4
- import { useTranslation } from './i18n.ts';
5
-
6
- export function GateResults(props: {
7
- readonly results: readonly GateResult[];
8
- readonly running: boolean;
9
- readonly error: string;
10
- readonly onClose: () => void;
11
- }) @{
12
- const { t } = useTranslation();
13
- <Drawer
14
- open
15
- title={t('sandbox.gates.title')}
16
- width="lg"
17
- onClose={props.onClose}
18
- >
19
- <div class="ui-drawer__body">
20
- <div class="ui-view">
21
- @if (props.running) {
22
- <p role="status">{t('sandbox.gates.running')}</p>
23
- } @else if (props.error) {
24
- <Alert>{props.error}</Alert>
25
- } @else if (props.results.length === 0) {
26
- <Alert tone="warning">{t('sandbox.app.gates.none')}</Alert>
27
- }
28
- @for (const gate of props.results; key (gate.module ?? '') + ':' +
29
- gate.id) {
30
- <section class="ui-card">
31
- <div class="ui-card__head">
32
- <h3 class="ui-card__title">{gateLabel(gate.id)}</h3>
33
- <Tag
34
- tone={gate.status === 'passed'
35
- ? 'success'
36
- : gate.status === 'failed'
37
- ? 'danger'
38
- : 'warning'}
39
- >{t('sandbox.gates.status.' + gate.status)}</Tag>
40
- </div>
41
- <div class="ui-card__body">
42
- <p>{t('sandbox.gates.module', {
43
- module: gate.module ?? t('sandbox.gates.workspace'),
44
- })}</p>
45
- <p>{t('sandbox.gates.explain.' + gate.status)}</p>
46
- @if (gate.output || gate.command) {
47
- <details open={gate.status === 'failed'}>
48
- <summary>{t('sandbox.gates.details')}</summary>
49
- <div class="ui-table-wrap">
50
- <pre class="ui-code">{gate.output || gate.command}</pre>
51
- </div>
52
- </details>
53
- }
54
- </div>
55
- </section>
56
- }
57
- </div>
58
- </div>
59
- </Drawer>
60
- }