@littlebearapps/platform-admin-sdk 2.1.0 → 2.3.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 (122) hide show
  1. package/README.md +2 -5
  2. package/dist/check-upgrade.d.ts +29 -0
  3. package/dist/check-upgrade.js +97 -0
  4. package/dist/index.js +59 -4
  5. package/dist/manifest.d.ts +2 -0
  6. package/dist/scaffold.js +5 -1
  7. package/dist/templates.d.ts +6 -1
  8. package/dist/templates.js +141 -3
  9. package/dist/upgrade.d.ts +1 -0
  10. package/dist/upgrade.js +21 -2
  11. package/package.json +1 -1
  12. package/templates/full/dashboard/src/components/notifications/NotificationDropdown.tsx +130 -0
  13. package/templates/full/dashboard/src/components/notifications/NotificationItem.tsx +264 -0
  14. package/templates/full/dashboard/src/components/patterns/PatternInfoButton.tsx +60 -0
  15. package/templates/full/dashboard/src/components/reports/FeatureUsageReport.tsx +339 -0
  16. package/templates/full/dashboard/src/components/search/SearchResultGroup.tsx +46 -0
  17. package/templates/full/dashboard/src/components/search/SearchResultItem.tsx +212 -0
  18. package/templates/full/dashboard/src/pages/api/patterns/[id]/approve.ts +49 -0
  19. package/templates/full/dashboard/src/pages/api/patterns/[id]/reject.ts +50 -0
  20. package/templates/full/dashboard/src/pages/api/reports/digests/stats.ts +38 -0
  21. package/templates/full/dashboard/src/pages/api/reports/digests.ts +39 -0
  22. package/templates/full/dashboard/src/pages/api/search/reindex/[type].ts +56 -0
  23. package/templates/full/dashboard/src/pages/api/test-reports/[id].ts +102 -0
  24. package/templates/full/dashboard/src/pages/feedback.astro +365 -0
  25. package/templates/full/dashboard/src/pages/kiosk.astro +206 -0
  26. package/templates/full/dashboard/src/pages/map.astro +561 -0
  27. package/templates/full/dashboard/src/pages/revenue.astro +72 -0
  28. package/templates/full/dashboard/src/pages/tests.astro +431 -0
  29. package/templates/full/scripts/ops/audit-cost-anomaly.ts +430 -0
  30. package/templates/full/scripts/ops/verify-account-total.ts +256 -0
  31. package/templates/full/tests/integration/feedback-schema.test.ts +361 -0
  32. package/templates/full/tests/integration/r2-archive.test.ts +108 -0
  33. package/templates/shared/.github/workflows/dependabot-automerge.yml +41 -0
  34. package/templates/shared/.github/workflows/validate-controls.yml +27 -0
  35. package/templates/shared/dashboard/src/components/Breadcrumbs.astro +101 -0
  36. package/templates/shared/dashboard/src/components/EmptyState.astro +46 -0
  37. package/templates/shared/dashboard/src/components/ErrorBoundary.astro +79 -0
  38. package/templates/shared/dashboard/src/components/LoadingSkeleton.astro +105 -0
  39. package/templates/shared/dashboard/src/components/PageShell.astro +72 -0
  40. package/templates/shared/dashboard/src/components/SkipLinks.astro +22 -0
  41. package/templates/shared/dashboard/src/components/Toast.astro +170 -0
  42. package/templates/shared/dashboard/src/components/ToastContainer.astro +156 -0
  43. package/templates/shared/dashboard/src/components/costs/ProviderCostsGrid.tsx +401 -0
  44. package/templates/shared/dashboard/src/components/costs/index.ts +4 -0
  45. package/templates/shared/dashboard/src/components/overview/AlertBanner.tsx +94 -0
  46. package/templates/shared/dashboard/src/components/overview/index.ts +9 -0
  47. package/templates/shared/dashboard/src/components/resources/CostChart.tsx +170 -0
  48. package/templates/shared/dashboard/src/components/resources/ProviderCard.tsx +272 -0
  49. package/templates/shared/dashboard/src/components/resources/ProviderDetail.tsx +293 -0
  50. package/templates/shared/dashboard/src/components/settings/SettingsCard.astro +102 -0
  51. package/templates/shared/dashboard/src/components/usage/AllowanceGauge.astro +170 -0
  52. package/templates/shared/dashboard/src/components/usage/AnomalyAlerts.astro +633 -0
  53. package/templates/shared/dashboard/src/components/usage/BillingCycleCountdown.astro +192 -0
  54. package/templates/shared/dashboard/src/components/usage/BurnRateHero.astro +539 -0
  55. package/templates/shared/dashboard/src/components/usage/CircuitBreakerEventLog.astro +542 -0
  56. package/templates/shared/dashboard/src/components/usage/CircuitBreakerPanel.tsx +292 -0
  57. package/templates/shared/dashboard/src/components/usage/CircuitBreakerStatus.astro +669 -0
  58. package/templates/shared/dashboard/src/components/usage/CompactThresholdBanner.astro +531 -0
  59. package/templates/shared/dashboard/src/components/usage/ComparisonModeSelector.astro +651 -0
  60. package/templates/shared/dashboard/src/components/usage/CostBreakdownChart.astro +381 -0
  61. package/templates/shared/dashboard/src/components/usage/CostBreakdownTable.astro +210 -0
  62. package/templates/shared/dashboard/src/components/usage/CostDataTable.astro +0 -0
  63. package/templates/shared/dashboard/src/components/usage/CostDonutChart.astro +311 -0
  64. package/templates/shared/dashboard/src/components/usage/DailyCostChart.astro +632 -0
  65. package/templates/shared/dashboard/src/components/usage/ExportButton.astro +114 -0
  66. package/templates/shared/dashboard/src/components/usage/FeatureBudgetsTable.astro +872 -0
  67. package/templates/shared/dashboard/src/components/usage/FilterBar.astro +190 -0
  68. package/templates/shared/dashboard/src/components/usage/FilterToggles.astro +175 -0
  69. package/templates/shared/dashboard/src/components/usage/GitHubUsageCard.astro +537 -0
  70. package/templates/shared/dashboard/src/components/usage/OverageCostCard.astro +212 -0
  71. package/templates/shared/dashboard/src/components/usage/PlanUtilizationCard.astro +193 -0
  72. package/templates/shared/dashboard/src/components/usage/ProjectCard.astro +640 -0
  73. package/templates/shared/dashboard/src/components/usage/ProjectCardsGrid.astro +272 -0
  74. package/templates/shared/dashboard/src/components/usage/ResourceSearch.astro +279 -0
  75. package/templates/shared/dashboard/src/components/usage/ServiceUtilizationList.astro +604 -0
  76. package/templates/shared/dashboard/src/components/usage/SparklineCard.astro +399 -0
  77. package/templates/shared/dashboard/src/components/usage/StatsHero.astro +600 -0
  78. package/templates/shared/dashboard/src/components/usage/TableFilters.astro +1033 -0
  79. package/templates/shared/dashboard/src/components/usage/ThresholdAlert.astro +271 -0
  80. package/templates/shared/dashboard/src/components/usage/ThresholdSettings.astro +618 -0
  81. package/templates/shared/dashboard/src/components/usage/TopSpenderCard.astro +170 -0
  82. package/templates/shared/dashboard/src/components/usage/UnifiedResourceTable.astro +1737 -0
  83. package/templates/shared/dashboard/src/components/usage/UsageCard.astro +135 -0
  84. package/templates/shared/dashboard/src/components/usage/UsageHealthBanner.astro +387 -0
  85. package/templates/shared/dashboard/src/components/usage/UtilizationBar.astro +159 -0
  86. package/templates/shared/dashboard/src/components/usage/WorkersBreakdownTable.astro +659 -0
  87. package/templates/shared/dashboard/src/components/usage/daily/CostChart.astro +461 -0
  88. package/templates/shared/dashboard/src/components/usage/daily/CostTable.astro +946 -0
  89. package/templates/shared/dashboard/src/components/usage/daily/DailyOverview.astro +1079 -0
  90. package/templates/shared/dashboard/src/components/usage/design-tokens.ts +187 -0
  91. package/templates/shared/dashboard/src/components/usage/filters/InlineDateRange.astro +285 -0
  92. package/templates/shared/dashboard/src/components/usage/filters/PeriodButtons.astro +157 -0
  93. package/templates/shared/dashboard/src/components/usage/filters/ProjectSelect.astro +284 -0
  94. package/templates/shared/dashboard/src/components/usage/scripts/ai-tab-controller.ts +419 -0
  95. package/templates/shared/dashboard/src/components/usage/scripts/constants.ts +60 -0
  96. package/templates/shared/dashboard/src/components/usage/scripts/formatters.ts +62 -0
  97. package/templates/shared/dashboard/src/components/usage/scripts/overview-controller.ts +1633 -0
  98. package/templates/shared/dashboard/src/components/usage/scripts/resource-table-builder.ts +294 -0
  99. package/templates/shared/dashboard/src/components/usage/scripts/tabs-filters-controller.ts +464 -0
  100. package/templates/shared/dashboard/src/components/usage/state/index.ts +55 -0
  101. package/templates/shared/dashboard/src/components/usage/state/usageActions.ts +439 -0
  102. package/templates/shared/dashboard/src/components/usage/state/usageStore.ts +376 -0
  103. package/templates/shared/dashboard/src/components/usage/types.ts +283 -0
  104. package/templates/shared/dashboard/src/components/usage/usage-colors.ts +292 -0
  105. package/templates/shared/dashboard/src/pages/api/usage/ai-models.ts +235 -0
  106. package/templates/shared/dashboard/src/pages/api/usage/billing-context.ts +296 -0
  107. package/templates/shared/scripts/test-telemetry-flow.ts +464 -0
  108. package/templates/shared/tests/e2e/usage-export.test.ts +784 -0
  109. package/templates/shared/tests/e2e/usage-mobile.test.ts +531 -0
  110. package/templates/standard/dashboard/src/components/errors/PriorityBadge.astro +27 -0
  111. package/templates/standard/dashboard/src/components/infrastructure/HealthchecksStatus.tsx +293 -0
  112. package/templates/standard/dashboard/src/components/infrastructure/InfrastructureTabs.tsx +268 -0
  113. package/templates/standard/dashboard/src/pages/analytics.astro +64 -0
  114. package/templates/standard/dashboard/src/pages/api/infrastructure/alerts.ts +85 -0
  115. package/templates/standard/dashboard/src/pages/api/infrastructure/healthchecks/[id]/flips.ts +110 -0
  116. package/templates/standard/dashboard/src/pages/api/infrastructure/healthchecks.ts +101 -0
  117. package/templates/standard/dashboard/src/pages/api/infrastructure/uptime/[id]/response-times.ts +121 -0
  118. package/templates/standard/dashboard/src/pages/api/infrastructure/uptime.ts +89 -0
  119. package/templates/standard/dashboard/src/pages/api/test/service-auth.ts +178 -0
  120. package/templates/standard/tests/integration/connectors.test.ts +241 -0
  121. package/templates/standard/tests/integration/github-monitor.test.ts +143 -0
  122. package/templates/standard/tests/integration/ingestion.test.ts +211 -0
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Resource Table Builder
3
+ *
4
+ * Builds the unified resource table and mobile cards view.
5
+ * Extracted from index.astro for task-22.5 (slim to <300 lines)
6
+ */
7
+
8
+ // ========== Types ==========
9
+
10
+ export interface UnifiedResource {
11
+ id: string;
12
+ name: string;
13
+ type: string;
14
+ project: string;
15
+ /** GitHub repository URL for the project (if available) */
16
+ repoUrl?: string | null;
17
+ usage: {
18
+ value: number;
19
+ formatted: string;
20
+ unit: string;
21
+ };
22
+ /** Percentage of monthly limit used (0-100+) */
23
+ limitPct?: number | null;
24
+ costCurrent: number;
25
+ costPrior: number;
26
+ costDelta: number;
27
+ costDeltaPct: number | 'NEW';
28
+ status: 'healthy' | 'warning' | 'high' | 'critical';
29
+ }
30
+
31
+ // ========== Constants ==========
32
+
33
+ const TYPE_LABELS: Record<string, string> = {
34
+ worker: 'Worker',
35
+ d1: 'D1 Database',
36
+ kv: 'KV Namespace',
37
+ r2: 'R2 Bucket',
38
+ vectorize: 'Vectorize',
39
+ pages: 'Pages',
40
+ do: 'Durable Object',
41
+ 'ai-gateway': 'AI Gateway',
42
+ queues: 'Queues',
43
+ workflows: 'Workflows',
44
+ };
45
+
46
+ const STATUS_LABELS: Record<string, string> = {
47
+ healthy: 'Healthy',
48
+ warning: 'Warning',
49
+ high: 'High',
50
+ critical: 'Critical',
51
+ };
52
+
53
+ const STATUS_COLORS: Record<string, string> = {
54
+ healthy: 'status-healthy',
55
+ warning: 'status-warning',
56
+ high: 'status-high',
57
+ critical: 'status-critical',
58
+ };
59
+
60
+ const TABLE_HEADERS = [
61
+ { key: 'project', label: 'Project', align: 'left' },
62
+ { key: 'type', label: 'Type', align: 'left' },
63
+ { key: 'usage', label: 'Usage', align: 'right' },
64
+ { key: 'costCurrent', label: 'Est. Cost', align: 'right' },
65
+ { key: 'costDeltaPct', label: 'vs Prior', align: 'right' },
66
+ { key: 'status', label: 'Status', align: 'left' },
67
+ ];
68
+
69
+ // ========== DOM Helpers ==========
70
+
71
+ function clearElement(el: HTMLElement): void {
72
+ while (el.firstChild) {
73
+ el.removeChild(el.firstChild);
74
+ }
75
+ }
76
+
77
+ function createEmptyState(message: string): HTMLElement {
78
+ const div = document.createElement('div');
79
+ div.className = 'empty-state';
80
+ div.textContent = message;
81
+ return div;
82
+ }
83
+
84
+ // ========== Table Building ==========
85
+
86
+ function createTableHeader(): HTMLElement {
87
+ const thead = document.createElement('thead');
88
+ const headerRow = document.createElement('tr');
89
+
90
+ TABLE_HEADERS.forEach((header) => {
91
+ const th = document.createElement('th');
92
+ th.className = 'sortable';
93
+ th.setAttribute('data-sort', header.key);
94
+ if (header.align === 'right') {
95
+ th.style.textAlign = 'right';
96
+ }
97
+ th.textContent = header.label;
98
+ headerRow.appendChild(th);
99
+ });
100
+
101
+ thead.appendChild(headerRow);
102
+ return thead;
103
+ }
104
+
105
+ function createDeltaBadge(deltaPct: number | 'NEW'): HTMLElement {
106
+ const badge = document.createElement('span');
107
+
108
+ if (deltaPct === 'NEW') {
109
+ badge.className = 'delta-badge delta-new';
110
+ badge.textContent = 'NEW';
111
+ } else if (typeof deltaPct === 'number') {
112
+ // Show dash for unchanged values (within ±0.5%)
113
+ if (Math.abs(deltaPct) < 0.5) {
114
+ badge.className = 'delta-badge delta-neutral';
115
+ badge.textContent = '—';
116
+ } else {
117
+ const sign = deltaPct >= 0 ? '+' : '';
118
+ const colorClass = deltaPct > 5 ? 'delta-up' : deltaPct < -5 ? 'delta-down' : 'delta-neutral';
119
+ badge.className = 'delta-badge ' + colorClass;
120
+ badge.textContent = sign + deltaPct.toFixed(1) + '%';
121
+ }
122
+ }
123
+
124
+ return badge;
125
+ }
126
+
127
+ function createStatusBadge(status: string): HTMLElement {
128
+ const badge = document.createElement('span');
129
+ badge.className = 'status-badge ' + (STATUS_COLORS[status] || '');
130
+ badge.textContent = STATUS_LABELS[status] || status;
131
+ return badge;
132
+ }
133
+
134
+ function createTableRow(resource: UnifiedResource): HTMLElement {
135
+ const row = document.createElement('tr');
136
+
137
+ // Add data-status for critical row highlighting
138
+ row.setAttribute('data-status', resource.status);
139
+
140
+ // Project cell (monospace for project IDs)
141
+ const projectCell = document.createElement('td');
142
+ projectCell.className = 'script-name';
143
+ projectCell.textContent = resource.name || resource.project || resource.id || 'Unknown';
144
+ row.appendChild(projectCell);
145
+
146
+ // Type cell
147
+ const typeCell = document.createElement('td');
148
+ typeCell.textContent = TYPE_LABELS[resource.type] || resource.type;
149
+ row.appendChild(typeCell);
150
+
151
+ // Usage cell (right-aligned)
152
+ const usageCell = document.createElement('td');
153
+ usageCell.className = 'text-right';
154
+ usageCell.textContent = resource.usage.formatted + ' ' + resource.usage.unit;
155
+ row.appendChild(usageCell);
156
+
157
+ // Cost cell (right-aligned)
158
+ const costCell = document.createElement('td');
159
+ costCell.className = 'font-semibold text-right';
160
+ costCell.textContent = '$' + resource.costCurrent.toFixed(2);
161
+ row.appendChild(costCell);
162
+
163
+ // Delta cell (right-aligned)
164
+ const deltaCell = document.createElement('td');
165
+ deltaCell.className = 'text-right';
166
+ if (resource.costDeltaPct === 'NEW' || typeof resource.costDeltaPct === 'number') {
167
+ deltaCell.appendChild(createDeltaBadge(resource.costDeltaPct));
168
+ } else {
169
+ deltaCell.textContent = '—';
170
+ }
171
+ row.appendChild(deltaCell);
172
+
173
+ // Status cell
174
+ const statusCell = document.createElement('td');
175
+ statusCell.appendChild(createStatusBadge(resource.status));
176
+ row.appendChild(statusCell);
177
+
178
+ return row;
179
+ }
180
+
181
+ function createTableBody(resources: UnifiedResource[]): HTMLElement {
182
+ const tbody = document.createElement('tbody');
183
+
184
+ resources.forEach((resource) => {
185
+ tbody.appendChild(createTableRow(resource));
186
+ });
187
+
188
+ return tbody;
189
+ }
190
+
191
+ // ========== Mobile Cards ==========
192
+
193
+ function createMobileCard(resource: UnifiedResource): HTMLElement {
194
+ const card = document.createElement('div');
195
+ card.className = 'mobile-card';
196
+
197
+ // Add data-status for critical card highlighting
198
+ card.setAttribute('data-status', resource.status);
199
+
200
+ const cardHeader = document.createElement('div');
201
+ cardHeader.className = 'mobile-card-header';
202
+ cardHeader.textContent = resource.name || resource.project || resource.id || 'Unknown';
203
+ card.appendChild(cardHeader);
204
+
205
+ const cardBody = document.createElement('div');
206
+ cardBody.className = 'mobile-card-body';
207
+
208
+ const rows = [
209
+ { label: 'Type', value: TYPE_LABELS[resource.type] || resource.type },
210
+ { label: 'Usage', value: resource.usage.formatted + ' ' + resource.usage.unit },
211
+ { label: 'Est. Cost', value: '$' + resource.costCurrent.toFixed(2) },
212
+ { label: 'Status', value: STATUS_LABELS[resource.status] || resource.status },
213
+ ];
214
+
215
+ rows.forEach((rowData) => {
216
+ const row = document.createElement('div');
217
+ row.className = 'mobile-card-row';
218
+
219
+ const label = document.createElement('span');
220
+ label.className = 'mobile-card-label';
221
+ label.textContent = rowData.label;
222
+ row.appendChild(label);
223
+
224
+ const value = document.createElement('span');
225
+ value.className = 'mobile-card-value';
226
+ value.textContent = rowData.value;
227
+ row.appendChild(value);
228
+
229
+ cardBody.appendChild(row);
230
+ });
231
+
232
+ card.appendChild(cardBody);
233
+ return card;
234
+ }
235
+
236
+ function createMobileCards(resources: UnifiedResource[]): HTMLElement {
237
+ const mobileCards = document.createElement('div');
238
+ mobileCards.className = 'mobile-cards';
239
+
240
+ resources.forEach((resource) => {
241
+ mobileCards.appendChild(createMobileCard(resource));
242
+ });
243
+
244
+ return mobileCards;
245
+ }
246
+
247
+ // ========== Main Render Function ==========
248
+
249
+ export function renderResourceTable(resources: UnifiedResource[]): void {
250
+ const container = document.getElementById('unified-table-container');
251
+ if (!container) return;
252
+
253
+ // Clear container
254
+ clearElement(container);
255
+
256
+ if (resources.length === 0) {
257
+ container.appendChild(createEmptyState('No resources match the current filters.'));
258
+ return;
259
+ }
260
+
261
+ // Create table
262
+ const tableWrapper = document.createElement('div');
263
+ tableWrapper.className = 'table-container responsive-table';
264
+
265
+ const tableDiv = document.createElement('div');
266
+ tableDiv.className = 'table-wrapper';
267
+
268
+ const table = document.createElement('table');
269
+ table.className = 'detail-table sortable-table';
270
+
271
+ table.appendChild(createTableHeader());
272
+ table.appendChild(createTableBody(resources));
273
+
274
+ tableDiv.appendChild(table);
275
+ tableWrapper.appendChild(tableDiv);
276
+
277
+ // Add mobile cards view
278
+ tableWrapper.appendChild(createMobileCards(resources));
279
+
280
+ container.appendChild(tableWrapper);
281
+ }
282
+
283
+ // ========== Resource Count Update ==========
284
+
285
+ export function updateResourceCount(count: number): void {
286
+ const countEl = document.getElementById('resource-count-value');
287
+ if (countEl) {
288
+ countEl.textContent = String(count);
289
+ }
290
+ }
291
+
292
+ // ========== Type/Status Label Exports ==========
293
+
294
+ export { TYPE_LABELS, STATUS_LABELS, STATUS_COLORS };