@growthub/cli 0.13.5 → 0.13.7

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 (39) hide show
  1. package/assets/worker-kits/growthub-custom-workspace-starter-v1/QUICKSTART.md +19 -0
  2. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/.env.example +8 -0
  3. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/README.md +4 -0
  4. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/action/execute/route.js +60 -0
  5. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/actions/route.js +50 -0
  6. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/connect-session/route.js +68 -0
  7. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/connection-status/route.js +56 -0
  8. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/proxy/route.js +67 -0
  9. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/integrations/nango/status/route.js +50 -0
  10. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/api/workspace/metadata-graph/route.js +1 -0
  11. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/components/WorkspaceActivationPanel.jsx +172 -0
  12. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/DataModelShell.jsx +161 -50
  13. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/data-model/components/NangoConnectionPanel.jsx +531 -0
  14. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/globals.css +274 -18
  15. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/settings/integrations/nango/page.jsx +167 -0
  16. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/settings/integrations/page.jsx +1 -0
  17. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workflows/WorkflowSurface.jsx +62 -7
  18. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workspace-builder.jsx +554 -48
  19. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/app/workspace-rail.jsx +24 -14
  20. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/env.js +7 -0
  21. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/index.js +38 -0
  22. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/nango-adapter.js +552 -0
  23. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/nango-config-loader.js +202 -0
  24. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/nango/nango-schema.js +303 -0
  25. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/resolver-loader.js +49 -10
  26. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/source-resolver-registry.js +1 -1
  27. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/nango.js +49 -0
  28. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/adapters/integrations/templates/template-registry.js +4 -2
  29. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/orchestration-graph.js +2 -2
  30. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-activation.js +534 -0
  31. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-data-model.js +3 -1
  32. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-metadata-store.js +82 -0
  33. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/lib/workspace-schema.js +102 -3
  34. package/assets/worker-kits/growthub-custom-workspace-starter-v1/apps/workspace/package.json +1 -0
  35. package/assets/worker-kits/growthub-custom-workspace-starter-v1/bundles/growthub-custom-workspace-starter-v1.json +1 -0
  36. package/assets/worker-kits/growthub-custom-workspace-starter-v1/kit.json +5 -0
  37. package/assets/worker-kits/growthub-custom-workspace-starter-v1/templates/seeded-configs/project-management.config.json +276 -0
  38. package/dist/index.js +127 -44
  39. package/package.json +1 -1
@@ -396,6 +396,7 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
396
396
  }
397
397
 
398
398
  .workspace-builder {
399
+ --workspace-rail-width: 264px;
399
400
  min-height: 100vh;
400
401
  display: grid;
401
402
  grid-template-columns: 264px minmax(0, 1fr) 320px;
@@ -427,6 +428,7 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0
427
428
  overflow: hidden;
428
429
  }
429
430
  body.workspace-rail-collapsed .workspace-builder {
431
+ --workspace-rail-width: 52px;
430
432
  grid-template-columns: 52px minmax(0, 1fr) 320px;
431
433
  }
432
434
  body.workspace-rail-collapsed .workspace-builder.workspace-settings-page {
@@ -456,24 +458,19 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
456
458
  .workspace-rail.is-collapsed .workspace-rail-topbar {
457
459
  justify-content: center;
458
460
  width: 100%;
461
+ display: contents;
459
462
  }
460
463
  .workspace-rail.is-collapsed .workspace-rail-topbar-actions {
461
- display: flex;
462
- flex-direction: column;
463
- justify-content: center;
464
- gap: 8px;
465
- }
466
- .workspace-rail.is-collapsed .workspace-rail-topbar-actions .workspace-rail-icon-btn {
467
- order: 2;
464
+ display: contents;
468
465
  }
469
466
  .workspace-rail.is-collapsed .workspace-rail-icon-btn[aria-pressed="true"] {
470
467
  order: 1;
471
468
  }
472
469
  .workspace-rail.is-collapsed .workspace-rail-icon-btn[data-rail-search] {
473
- order: 2;
470
+ order: 3;
474
471
  }
475
472
  .workspace-rail.is-collapsed .workspace-rail-icon-btn[aria-label="Workspace settings"] {
476
- order: 3;
473
+ order: 4;
477
474
  }
478
475
  .workspace-rail.is-collapsed .workspace-rail-icon-btn[aria-pressed="true"] svg {
479
476
  transform: rotate(180deg);
@@ -482,6 +479,7 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
482
479
  display: flex;
483
480
  justify-content: center;
484
481
  width: 100%;
482
+ order: 2;
485
483
  }
486
484
  .workspace-rail.is-collapsed .workspace-rail-tabs {
487
485
  flex-direction: column;
@@ -561,7 +559,10 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
561
559
  padding: 16px;
562
560
  display: flex;
563
561
  flex-direction: column;
564
- overflow: hidden;
562
+ overflow-y: auto;
563
+ overflow-x: hidden;
564
+ scrollbar-gutter: stable;
565
+ overscroll-behavior: contain;
565
566
  }
566
567
  .workspace-toolbar {
567
568
  min-height: 48px;
@@ -641,6 +642,54 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
641
642
  .workspace-tabs > button svg {
642
643
  flex: 0 0 auto;
643
644
  }
645
+ .workspace-toolbar-actions > .workspace-finish-setup-control {
646
+ gap: 0;
647
+ padding: 0;
648
+ overflow: hidden;
649
+ }
650
+ .workspace-finish-setup-trigger,
651
+ .workspace-finish-setup-dismiss {
652
+ min-height: 28px;
653
+ border: 0;
654
+ background: transparent;
655
+ color: inherit;
656
+ display: inline-flex;
657
+ align-items: center;
658
+ justify-content: center;
659
+ gap: 6px;
660
+ padding: 0 10px;
661
+ cursor: pointer;
662
+ }
663
+ .workspace-finish-setup-trigger:hover,
664
+ .workspace-finish-setup-dismiss:hover {
665
+ background: #fafafa;
666
+ }
667
+ .workspace-finish-setup-control.is-complete {
668
+ border-color: #bbf7d0;
669
+ color: #047857;
670
+ background: #f0fdf4;
671
+ }
672
+ .workspace-finish-setup-control.is-complete .workspace-finish-setup-trigger:hover,
673
+ .workspace-finish-setup-control.is-complete .workspace-finish-setup-dismiss:hover {
674
+ background: #dcfce7;
675
+ }
676
+ .workspace-finish-setup-dismiss {
677
+ width: 30px;
678
+ padding: 0;
679
+ border-left: 1px solid #bbf7d0;
680
+ }
681
+ .workspace-finish-setup-dismiss-x {
682
+ display: none;
683
+ }
684
+ .workspace-finish-setup-dismiss:hover {
685
+ color: #b91c1c;
686
+ }
687
+ .workspace-finish-setup-dismiss:hover .workspace-finish-setup-dismiss-check {
688
+ display: none;
689
+ }
690
+ .workspace-finish-setup-dismiss:hover .workspace-finish-setup-dismiss-x {
691
+ display: block;
692
+ }
644
693
  .workspace-table,
645
694
  .workspace-canvas {
646
695
  border: 1px solid #e7e7e7;
@@ -2128,6 +2177,63 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
2128
2177
  transition: opacity .12s ease;
2129
2178
  }
2130
2179
 
2180
+ .workspace-dashboard-surface {
2181
+ background: #f7f7f8;
2182
+ padding: 0 32px 24px;
2183
+ }
2184
+ .workspace-dashboard-surface .dm-workflow-toolbar {
2185
+ margin: 0 0 18px;
2186
+ padding: 0;
2187
+ background: #ffffff;
2188
+ border-bottom-color: #e8e8e8;
2189
+ }
2190
+ .workspace-dashboard-surface .workspace-canvas {
2191
+ width: 100%;
2192
+ margin: 0 auto;
2193
+ border: 1px solid #e5e7eb;
2194
+ border-radius: 8px;
2195
+ background: #f7f7f8;
2196
+ max-height: calc(100vh - 72px);
2197
+ }
2198
+ .workspace-dashboard-surface .workspace-tabs {
2199
+ gap: 6px;
2200
+ min-height: 44px;
2201
+ padding: 8px 12px 12px;
2202
+ background: #ffffff;
2203
+ border-bottom: 1px solid #ececec;
2204
+ border-radius: 8px 8px 0 0;
2205
+ }
2206
+ .workspace-dashboard-surface .workspace-tabs button {
2207
+ min-height: 30px;
2208
+ }
2209
+ .workspace-dashboard-surface .workspace-grid {
2210
+ gap: 12px;
2211
+ padding: 18px;
2212
+ }
2213
+ .workspace-dashboard-surface .workspace-grid-cell {
2214
+ background: #ffffff;
2215
+ border-color: #e8e8e8;
2216
+ }
2217
+ .workspace-dashboard-surface.is-dashboard-editing {
2218
+ padding-inline: 16px;
2219
+ }
2220
+ .workspace-dashboard-surface.is-dashboard-editing .workspace-canvas {
2221
+ max-height: calc(100vh - 64px);
2222
+ }
2223
+ .workspace-dashboard-surface.is-dashboard-editing .workspace-grid {
2224
+ gap: 10px;
2225
+ padding: 14px;
2226
+ }
2227
+
2228
+ @media (max-width: 900px) {
2229
+ .workspace-dashboard-surface {
2230
+ padding-inline: 20px;
2231
+ }
2232
+ .workspace-dashboard-surface .dm-workflow-toolbar {
2233
+ margin-inline: 0;
2234
+ }
2235
+ }
2236
+
2131
2237
  @media (max-width: 1080px) {
2132
2238
  .workspace-builder {
2133
2239
  grid-template-columns: 180px minmax(0, 1fr);
@@ -4065,6 +4171,68 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
4065
4171
  .workspace-chart-type-tabs button.active em {
4066
4172
  color: #075985;
4067
4173
  }
4174
+ .workspace-table-view-tabs {
4175
+ grid-template-columns: repeat(4, 1fr);
4176
+ }
4177
+ .workspace-table-transform-preview {
4178
+ display: grid;
4179
+ gap: 8px;
4180
+ min-height: 88px;
4181
+ margin-top: 10px;
4182
+ color: #4b5563;
4183
+ font-size: 11px;
4184
+ }
4185
+ .workspace-table-transform-preview.is-board,
4186
+ .workspace-table-transform-preview.is-calendar {
4187
+ grid-template-columns: repeat(3, minmax(0, 1fr));
4188
+ }
4189
+ .workspace-table-transform-preview.is-calendar {
4190
+ grid-template-columns: repeat(5, minmax(0, 1fr));
4191
+ }
4192
+ .workspace-table-transform-preview section {
4193
+ min-width: 0;
4194
+ border: 1px solid #eeeeee;
4195
+ border-radius: 5px;
4196
+ background: #fafafa;
4197
+ padding: 6px;
4198
+ }
4199
+ .workspace-table-transform-preview strong,
4200
+ .workspace-table-transform-preview span,
4201
+ .workspace-table-transform-preview em {
4202
+ display: block;
4203
+ min-width: 0;
4204
+ overflow: hidden;
4205
+ text-overflow: ellipsis;
4206
+ white-space: nowrap;
4207
+ }
4208
+ .workspace-table-transform-preview strong {
4209
+ color: #111827;
4210
+ font-size: 11px;
4211
+ }
4212
+ .workspace-table-transform-preview span {
4213
+ margin-top: 5px;
4214
+ border-radius: 4px;
4215
+ background: #fff;
4216
+ padding: 5px 6px;
4217
+ }
4218
+ .workspace-table-transform-preview div {
4219
+ display: grid;
4220
+ grid-template-columns: minmax(64px, 1fr) 2fr minmax(32px, auto);
4221
+ align-items: center;
4222
+ gap: 8px;
4223
+ }
4224
+ .workspace-table-transform-preview i {
4225
+ display: block;
4226
+ width: var(--width, 42%);
4227
+ height: 9px;
4228
+ margin-left: var(--offset, 0);
4229
+ border-radius: 999px;
4230
+ background: #93c5fd;
4231
+ }
4232
+ .workspace-table-transform-preview em {
4233
+ color: #9ca3af;
4234
+ font-style: normal;
4235
+ }
4068
4236
  .workspace-axis-range {
4069
4237
  display: grid;
4070
4238
  grid-template-columns: 1fr 1fr;
@@ -4890,32 +5058,49 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
4890
5058
  background: #f7f7f8;
4891
5059
  overflow: hidden;
4892
5060
  }
5061
+ .workspace-surface.workspace-dashboard-surface {
5062
+ background: #f7f7f8;
5063
+ padding: 0 32px 24px;
5064
+ }
5065
+ .workspace-surface.workspace-dashboard-surface.is-dashboard-editing {
5066
+ padding-inline: 16px;
5067
+ }
4893
5068
  .dm-workflow-toolbar {
4894
5069
  height: 40px;
4895
5070
  min-height: 40px;
4896
5071
  align-items: center;
4897
5072
  flex-wrap: nowrap;
4898
5073
  gap: 12px;
4899
- padding: 0 12px;
4900
- margin: 0;
5074
+ padding: 0 32px;
5075
+ margin: 0 -32px 18px;
4901
5076
  border-bottom: 1px solid #ececef;
4902
5077
  background: #fbfbfc;
4903
5078
  overflow: hidden;
4904
5079
  }
5080
+ .workspace-surface.workspace-dashboard-surface .dm-workflow-toolbar {
5081
+ padding-inline: 32px;
5082
+ margin-inline: -32px;
5083
+ }
5084
+ .workspace-dashboard-surface.is-dashboard-editing .dm-workflow-toolbar {
5085
+ padding-inline: 16px;
5086
+ margin-inline: -16px;
5087
+ }
4905
5088
  .dm-workflow-titlebar {
4906
5089
  display: flex;
4907
5090
  align-items: center;
4908
5091
  gap: 6px;
4909
- min-width: 0;
4910
- flex: 1;
5092
+ min-width: max-content;
5093
+ flex: 1 0 auto;
4911
5094
  color: #8b8b91;
4912
5095
  font-size: 13px;
4913
5096
  font-weight: 500;
5097
+ white-space: nowrap;
4914
5098
  }
4915
5099
  .dm-workflow-titlebar h1 {
4916
5100
  margin: 0;
4917
- min-width: 0;
4918
- max-width: 260px;
5101
+ min-width: max-content;
5102
+ max-width: none;
5103
+ flex: 0 0 auto;
4919
5104
  overflow: hidden;
4920
5105
  text-overflow: ellipsis;
4921
5106
  white-space: nowrap;
@@ -4924,6 +5109,20 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
4924
5109
  font-weight: 600;
4925
5110
  letter-spacing: 0;
4926
5111
  }
5112
+ .dm-workflow-breadcrumb-link {
5113
+ appearance: none;
5114
+ border: 0;
5115
+ background: transparent;
5116
+ padding: 0;
5117
+ color: #a1a1aa;
5118
+ font: inherit;
5119
+ font-size: 13px;
5120
+ font-weight: 600;
5121
+ cursor: pointer;
5122
+ }
5123
+ .dm-workflow-breadcrumb-link:hover {
5124
+ color: #4b4b52;
5125
+ }
4927
5126
  .dm-workflow-title-icon {
4928
5127
  display: grid;
4929
5128
  place-items: center;
@@ -4943,8 +5142,9 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
4943
5142
  display: flex;
4944
5143
  align-items: center;
4945
5144
  gap: 6px;
4946
- flex-shrink: 0;
4947
- max-width: 66vw;
5145
+ flex: 0 1 auto;
5146
+ min-width: 0;
5147
+ max-width: 58vw;
4948
5148
  overflow-x: auto;
4949
5149
  scrollbar-width: none;
4950
5150
  }
@@ -8414,3 +8614,59 @@ body.workspace-rail-collapsed .workspace-builder.dm-workflow-page {
8414
8614
  .dm-swarm-phase { border: 1px solid #edf0f3; border-radius: 4px; padding: 6px 8px; font-size: 11px; }
8415
8615
  .dm-swarm-phase summary { cursor: pointer; color: #6b7280; font-weight: 500; }
8416
8616
  .dm-swarm-phase pre { margin: 6px 0 0; font-size: 11px; white-space: pre-wrap; color: #111827; max-height: 240px; overflow: auto; }
8617
+
8618
+ /* Customer Activation Layer V1 — workspace activation panel */
8619
+ .workspace-activation-panel { border: 1px solid #e5e7eb; border-radius: 10px; background: #ffffff; padding: 18px 20px; margin: 0 0 20px; display: flex; flex-direction: column; gap: 16px; }
8620
+ .workspace-activation-panel.is-complete { background: linear-gradient(180deg, #f0fdf4 0%, #ffffff 80%); border-color: #bbf7d0; }
8621
+ .workspace-activation-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
8622
+ .workspace-activation-head-text { display: flex; flex-direction: column; gap: 4px; flex: 1 1 320px; min-width: 0; }
8623
+ .workspace-activation-eyebrow { margin: 0; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: #6b7280; font-weight: 600; }
8624
+ .workspace-activation-headline { margin: 0; font-size: 18px; font-weight: 600; color: #111827; line-height: 1.3; }
8625
+ .workspace-activation-subheadline { margin: 0; font-size: 13px; color: #4b5563; }
8626
+ .workspace-activation-progress { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 120px; }
8627
+ .workspace-activation-progress-value { font-size: 11px; font-weight: 600; color: #475569; }
8628
+ .workspace-activation-progress-bar { display: block; width: 120px; height: 6px; background: #f1f5f9; border-radius: 999px; overflow: hidden; }
8629
+ .workspace-activation-progress-fill { display: block; height: 100%; background: #3b82f6; transition: width 200ms ease; }
8630
+ .workspace-activation-panel.is-complete .workspace-activation-progress-fill { background: #16a34a; }
8631
+ .workspace-activation-steps { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
8632
+ .workspace-activation-step { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border: 1px solid #edf0f3; border-radius: 8px; background: #fbfcfd; transition: border-color 120ms ease, background 120ms ease; }
8633
+ .workspace-activation-step.is-next { border-color: #3b82f6; background: #eff6ff; }
8634
+ .workspace-activation-step.is-complete { background: #f0fdf4; border-color: #bbf7d0; }
8635
+ .workspace-activation-step.is-blocked { background: #fffbeb; border-color: #fde68a; }
8636
+ .workspace-activation-step.is-optional { opacity: 0.85; }
8637
+ .workspace-activation-step-status { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 999px; background: #ffffff; border: 1px solid #cbd5f5; color: #3b82f6; flex-shrink: 0; }
8638
+ .workspace-activation-step.is-complete .workspace-activation-step-status { background: #16a34a; border-color: #16a34a; color: #ffffff; }
8639
+ .workspace-activation-step.is-blocked .workspace-activation-step-status { background: #fef3c7; border-color: #f59e0b; color: #b45309; }
8640
+ .workspace-activation-step.is-optional .workspace-activation-step-status { background: #f5f3ff; border-color: #c4b5fd; color: #7c3aed; }
8641
+ .workspace-activation-step-body { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
8642
+ .workspace-activation-step-titlebar { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
8643
+ .workspace-activation-step-title { margin: 0; font-size: 13px; font-weight: 600; color: #111827; }
8644
+ .workspace-activation-step-badge { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; padding: 1px 6px; border-radius: 999px; background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }
8645
+ .workspace-activation-step-badge.is-complete { background: #ecfdf5; color: #047857; border-color: #a7f3d0; }
8646
+ .workspace-activation-step-badge.is-blocked { background: #fef3c7; color: #b45309; border-color: #fde68a; }
8647
+ .workspace-activation-step-badge.is-optional { background: #f5f3ff; color: #6d28d9; border-color: #ddd6fe; }
8648
+ .workspace-activation-step-description { margin: 0; font-size: 12px; color: #475569; line-height: 1.5; }
8649
+ .workspace-activation-step-hint { display: inline-flex; align-items: flex-start; gap: 6px; margin: 0; font-size: 11px; color: #6b7280; line-height: 1.45; }
8650
+ .workspace-activation-step-hint > svg { margin-top: 2px; flex-shrink: 0; }
8651
+ .workspace-activation-step-cta { display: inline-flex; align-items: center; gap: 4px; align-self: flex-start; font-size: 12px; color: #1d4ed8; text-decoration: none; padding: 4px 0; }
8652
+ .workspace-activation-step-cta:hover { text-decoration: underline; }
8653
+ .workspace-activation-step-cta.is-primary { background: #3b82f6; color: #ffffff; border-radius: 6px; padding: 4px 10px; }
8654
+ .workspace-activation-step-cta.is-primary:hover { background: #2563eb; text-decoration: none; }
8655
+ .workspace-activation-helper-cta { display: flex; justify-content: flex-end; }
8656
+ .workspace-activation-helper-btn { display: inline-flex; align-items: center; gap: 6px; background: transparent; border: 1px dashed #c7d2fe; color: #4338ca; font-size: 12px; padding: 6px 10px; border-radius: 6px; cursor: pointer; }
8657
+ .workspace-activation-helper-btn:hover { background: #eef2ff; }
8658
+
8659
+ /* Compact rail variant — slim activation chip in WorkspaceRail Home */
8660
+ .workspace-activation-panel.is-compact { padding: 12px 14px; margin: 0 0 12px; gap: 10px; border-radius: 8px; }
8661
+ .workspace-activation-panel.is-compact .workspace-activation-head { gap: 8px; }
8662
+ .workspace-activation-panel.is-compact .workspace-activation-headline { font-size: 13px; }
8663
+ .workspace-activation-panel.is-compact .workspace-activation-subheadline { font-size: 11px; }
8664
+ .workspace-activation-panel.is-compact .workspace-activation-step { padding: 8px 10px; gap: 8px; }
8665
+ .workspace-activation-panel.is-compact .workspace-activation-step-title { font-size: 12px; }
8666
+ .workspace-activation-panel.is-compact .workspace-activation-step-description { font-size: 11px; }
8667
+ .workspace-activation-panel.is-compact .workspace-activation-progress-bar { width: 80px; }
8668
+
8669
+ /* Template-aware context banner — workflow + nango affordance */
8670
+ .workspace-template-context-banner { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 6px; background: #eff6ff; border: 1px solid #bfdbfe; color: #1e40af; font-size: 12px; margin: 0 0 12px; }
8671
+ .workspace-template-context-banner.is-warn { background: #fffbeb; border-color: #fde68a; color: #92400e; }
8672
+ .workspace-template-context-banner .workspace-template-context-link { color: inherit; text-decoration: underline; font-weight: 600; margin-left: auto; }
@@ -0,0 +1,167 @@
1
+ import Link from "next/link";
2
+ import { Suspense } from "react";
3
+ import { describeNangoAdapter, getStatus } from "@/lib/adapters/integrations/nango";
4
+ import { readWorkspaceConfig } from "@/lib/workspace-config";
5
+ import { WorkspaceRail } from "../../../workspace-rail.jsx";
6
+
7
+ /**
8
+ * Nango integration settings — inspect-only panel.
9
+ *
10
+ * Reads from the EXISTING `objectType: "api-registry"` rows in
11
+ * `dataModel.objects[]`. Rows that declare `connectorKind: "nango"` are
12
+ * Nango-backed; other connectorKinds (http, mcp, chrome, tool) are shown
13
+ * here only for context — they keep going through their own resolvers.
14
+ *
15
+ * Secrets are not displayed. The Nango secret lives in env (default env-ref
16
+ * name: NANGO_SECRET_KEY); the row's `authRef` column names the env-ref.
17
+ */
18
+
19
+ function listApiRegistryObjects(workspaceConfig) {
20
+ const objects = workspaceConfig?.dataModel?.objects;
21
+ if (!Array.isArray(objects)) return [];
22
+ return objects.filter((object) => object?.objectType === "api-registry");
23
+ }
24
+
25
+ function flattenNangoRows(apiRegistryObjects) {
26
+ const rows = [];
27
+ for (const object of apiRegistryObjects) {
28
+ const objectRows = Array.isArray(object.rows) ? object.rows : [];
29
+ for (const row of objectRows) {
30
+ if (row?.connectorKind === "nango") {
31
+ rows.push({ object, row });
32
+ }
33
+ }
34
+ }
35
+ return rows;
36
+ }
37
+
38
+ function summarizeList(value) {
39
+ if (Array.isArray(value)) return value.filter(Boolean);
40
+ if (typeof value === "string" && value.trim()) {
41
+ return value.split(",").map((v) => v.trim()).filter(Boolean);
42
+ }
43
+ return [];
44
+ }
45
+
46
+ function NangoRowCard({ object, row }) {
47
+ const connectionIds = summarizeList(row.connectionIds);
48
+ const enabledActions = summarizeList(row.enabledActions);
49
+ const providerConfigKey = row.providerConfigKey || row.integrationId;
50
+ return <article className="workspace-integration-row">
51
+ <div className="workspace-provider-mark">{String(row.integrationId || "?").slice(0, 1).toUpperCase()}</div>
52
+ <div className="workspace-integration-main">
53
+ <strong>{row.integrationId}</strong>
54
+ <p>providerConfigKey: <code>{providerConfigKey || "—"}</code></p>
55
+ <div className="workspace-integration-meta">
56
+ <span>object: <code>{object.id}</code></span>
57
+ <span>{row.nangoMode || "cloud"}</span>
58
+ <span>env: {row.nangoEnvironment || "dev"}</span>
59
+ <span>{connectionIds.length} {connectionIds.length === 1 ? "connection" : "connections"}</span>
60
+ <span>{enabledActions.length} {enabledActions.length === 1 ? "action" : "actions"}</span>
61
+ {row.authRef ? <span><code>{row.authRef}</code></span> : null}
62
+ {row.endpoint ? <span>endpoint: <code>{row.endpoint}</code></span> : null}
63
+ </div>
64
+ </div>
65
+ <span className={`workspace-integration-status ${row.status || "configured"}`}>{row.status || "configured"}</span>
66
+ </article>;
67
+ }
68
+
69
+ async function NangoIntegrationsSettingsPage() {
70
+ const adapter = describeNangoAdapter();
71
+ const workspaceConfig = await readWorkspaceConfig();
72
+ const apiRegistryObjects = listApiRegistryObjects(workspaceConfig);
73
+ const nangoRows = flattenNangoRows(apiRegistryObjects);
74
+
75
+ let status;
76
+ try {
77
+ status = await getStatus();
78
+ } catch (error) {
79
+ status = { status: "disconnected", reason: error?.message || "status probe failed" };
80
+ }
81
+
82
+ return <main className="workspace-builder workspace-settings-page">
83
+ <Suspense fallback={null}>
84
+ <WorkspaceRail
85
+ workspaceConfig={workspaceConfig}
86
+ authority={adapter.authority}
87
+ managementSlot={(
88
+ <Link className="active" href="/settings/integrations">Integrations</Link>
89
+ )}
90
+ />
91
+ </Suspense>
92
+
93
+ <section className="workspace-surface">
94
+ <header className="workspace-toolbar">
95
+ <div>
96
+ <p>Workspace settings &middot; Integrations</p>
97
+ <h1>Nango</h1>
98
+ </div>
99
+ <div className="workspace-toolbar-actions">
100
+ <Link href="/settings/integrations">All integrations</Link>
101
+ <span>{adapter.id}</span>
102
+ <span>{adapter.authority}</span>
103
+ </div>
104
+ </header>
105
+
106
+ <section className="workspace-integration-summary" aria-label="Nango adapter summary">
107
+ <article>
108
+ <span>Adapter</span>
109
+ <strong>{adapter.label}</strong>
110
+ <div>
111
+ <code>{adapter.secretEnvName}</code>
112
+ <span> &middot; row-scoped via <code>connectorKind: "nango"</code></span>
113
+ </div>
114
+ </article>
115
+ <article>
116
+ <span>Mode</span>
117
+ <strong>{adapter.mode}</strong>
118
+ <div>{adapter.hostUrl ? <code>{adapter.hostUrl}</code> : <code>nango cloud</code>}</div>
119
+ </article>
120
+ <article>
121
+ <span>Status</span>
122
+ <strong>{status.status}</strong>
123
+ <div>{status.reason ? <span>{status.reason}</span> : <span>environment: <code>{status.environment || adapter.environment}</code></span>}</div>
124
+ </article>
125
+ </section>
126
+
127
+ <section className="workspace-integration-toolbar">
128
+ <div>
129
+ <strong>Nango-backed API Registry rows</strong>
130
+ <p>Rows in <code>dataModel.objects[]</code> with <code>objectType: "api-registry"</code> and <code>connectorKind: "nango"</code>. Edit <code>growthub.config.json</code> to add or remove rows — secrets stay in env, referenced by the row's <code>authRef</code>.</p>
131
+ </div>
132
+ </section>
133
+
134
+ <section className="workspace-integration-board">
135
+ {nangoRows.length === 0
136
+ ? <article className="workspace-integration-section">
137
+ <div className="workspace-integration-section-heading">
138
+ <div>
139
+ <h2>No Nango-backed rows yet</h2>
140
+ <p>Add a row to an <code>api-registry</code> object with <code>connectorKind: "nango"</code>, an <code>integrationId</code>, and an optional <code>providerConfigKey</code>. Apply the <code>nango</code> resolver template from the Data Model template picker for sensible defaults.</p>
141
+ </div>
142
+ </div>
143
+ </article>
144
+ : <article className="workspace-integration-section">
145
+ <div className="workspace-integration-section-heading">
146
+ <div>
147
+ <h2>Nango providers</h2>
148
+ <p>{nangoRows.length} row{nangoRows.length === 1 ? "" : "s"} across {apiRegistryObjects.length} API Registry object{apiRegistryObjects.length === 1 ? "" : "s"}.</p>
149
+ </div>
150
+ <span>{nangoRows.length}</span>
151
+ </div>
152
+ <div className="workspace-integration-list">
153
+ {nangoRows.map(({ object, row }, index) => <NangoRowCard
154
+ object={object}
155
+ row={row}
156
+ key={`${object.id}:${row.integrationId || index}`}
157
+ />)}
158
+ </div>
159
+ </article>}
160
+ </section>
161
+ </section>
162
+ </main>;
163
+ }
164
+
165
+ export {
166
+ NangoIntegrationsSettingsPage as default
167
+ };
@@ -77,6 +77,7 @@ async function IntegrationsSettingsPage() {
77
77
  </div>
78
78
  <div className="workspace-toolbar-actions">
79
79
  <Link href="/api/settings/integrations">API contract</Link>
80
+ <Link href="/settings/integrations/nango">Nango</Link>
80
81
  <span>{adapter.id}</span>
81
82
  <span>{adapter.authority}</span>
82
83
  </div>