@powerhousedao/builder-profile 0.0.5 → 0.0.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.
@@ -0,0 +1,180 @@
1
+ /**
2
+ * GraphQL client utility for fetching remote builder profiles from Switchboard.
3
+ * This is used as a fallback when local drives don't have the builder profile documents.
4
+ */
5
+ function getGraphQLUrl() {
6
+ if (typeof window === "undefined") {
7
+ return "http://localhost:4001/graphql";
8
+ }
9
+ if (!window.document.baseURI.includes("localhost")) {
10
+ return window.document.baseURI + "/graphql";
11
+ }
12
+ return "http://localhost:4001/graphql";
13
+ }
14
+ async function graphqlRequest(query, variables, options) {
15
+ try {
16
+ const response = await fetch(getGraphQLUrl(), {
17
+ method: "POST",
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ },
21
+ body: JSON.stringify({ query, variables }),
22
+ });
23
+ if (!response.ok) {
24
+ if (!options?.silent) {
25
+ console.warn("[graphql-client] Request failed:", response.status, response.statusText);
26
+ }
27
+ return null;
28
+ }
29
+ const result = (await response.json());
30
+ // Return data even if there are errors - partial data might still be useful
31
+ // Only treat as full failure if there's no data at all
32
+ if (result.errors?.length && !result.data) {
33
+ if (!options?.silent) {
34
+ console.warn("[graphql-client] GraphQL errors:", result.errors);
35
+ }
36
+ return null;
37
+ }
38
+ return result.data ?? null;
39
+ }
40
+ catch (error) {
41
+ // Silently fail - this is a fallback mechanism
42
+ if (!options?.silent) {
43
+ console.warn("[graphql-client] Request error:", error);
44
+ }
45
+ return null;
46
+ }
47
+ }
48
+ // Query to get all available drives
49
+ const GET_DRIVES_QUERY = `
50
+ query GetDrives {
51
+ drives
52
+ }
53
+ `;
54
+ // Query to get drive ID by slug
55
+ const GET_DRIVE_ID_BY_SLUG_QUERY = `
56
+ query GetDriveIdBySlug($slug: String!) {
57
+ driveIdBySlug(slug: $slug)
58
+ }
59
+ `;
60
+ // Query to get builder profile documents from a drive
61
+ const GET_BUILDER_PROFILES_QUERY = `
62
+ query GetBuilderProfiles($driveId: String!) {
63
+ BuilderProfile {
64
+ getDocuments(driveId: $driveId) {
65
+ id
66
+ state {
67
+ name
68
+ slug
69
+ icon
70
+ }
71
+ }
72
+ }
73
+ }
74
+ `;
75
+ // Query to get a single builder profile by ID
76
+ const GET_BUILDER_PROFILE_QUERY = `
77
+ query GetBuilderProfile($docId: PHID!, $driveId: PHID) {
78
+ BuilderProfile {
79
+ getDocument(docId: $docId, driveId: $driveId) {
80
+ id
81
+ state {
82
+ name
83
+ slug
84
+ icon
85
+ }
86
+ }
87
+ }
88
+ }
89
+ `;
90
+ /**
91
+ * Fetches all available remote drives
92
+ */
93
+ export async function fetchRemoteDrives() {
94
+ const data = await graphqlRequest(GET_DRIVES_QUERY);
95
+ return data?.drives ?? [];
96
+ }
97
+ /**
98
+ * Fetches drive ID by slug
99
+ */
100
+ export async function fetchDriveIdBySlug(slug) {
101
+ const data = await graphqlRequest(GET_DRIVE_ID_BY_SLUG_QUERY, { slug });
102
+ return data?.driveIdBySlug ?? null;
103
+ }
104
+ /**
105
+ * Fetches all builder profiles from a specific drive
106
+ */
107
+ export async function fetchBuilderProfilesFromDrive(driveId, options) {
108
+ const data = await graphqlRequest(GET_BUILDER_PROFILES_QUERY, { driveId }, options);
109
+ return data?.BuilderProfile?.getDocuments ?? [];
110
+ }
111
+ /**
112
+ * Fetches a single builder profile by document ID
113
+ */
114
+ export async function fetchBuilderProfileById(docId, driveId) {
115
+ const data = await graphqlRequest(GET_BUILDER_PROFILE_QUERY, { docId, driveId });
116
+ return data?.BuilderProfile?.getDocument ?? null;
117
+ }
118
+ /**
119
+ * Fetches all builder profiles from all available remote drives.
120
+ * This aggregates profiles from multiple drives into a single list.
121
+ */
122
+ export async function fetchAllRemoteBuilderProfiles() {
123
+ try {
124
+ const drives = await fetchRemoteDrives();
125
+ if (!drives.length) {
126
+ return [];
127
+ }
128
+ // Fetch profiles from all drives in parallel (silent to avoid console spam)
129
+ const profilePromises = drives.map((driveSlug) => fetchBuilderProfilesFromDrive(driveSlug, { silent: true }).catch(() => []));
130
+ const profileArrays = await Promise.all(profilePromises);
131
+ // Flatten and dedupe by ID
132
+ const profileMap = new Map();
133
+ for (const profiles of profileArrays) {
134
+ for (const profile of profiles) {
135
+ if (!profileMap.has(profile.id)) {
136
+ profileMap.set(profile.id, profile);
137
+ }
138
+ }
139
+ }
140
+ return Array.from(profileMap.values());
141
+ }
142
+ catch {
143
+ return [];
144
+ }
145
+ }
146
+ /**
147
+ * Fetches multiple builder profiles by their IDs.
148
+ * Tries to find them across all available remote drives.
149
+ */
150
+ export async function fetchRemoteBuilderProfilesByIds(phids) {
151
+ if (!phids.length) {
152
+ return new Map();
153
+ }
154
+ try {
155
+ // First, get all profiles from all drives
156
+ const allProfiles = await fetchAllRemoteBuilderProfiles();
157
+ // Filter to only the ones we need
158
+ const result = new Map();
159
+ for (const profile of allProfiles) {
160
+ if (phids.includes(profile.id)) {
161
+ result.set(profile.id, profile);
162
+ }
163
+ }
164
+ // For any missing profiles, try direct fetch
165
+ const missingPhids = phids.filter((phid) => !result.has(phid));
166
+ if (missingPhids.length > 0) {
167
+ const directFetches = missingPhids.map(async (phid) => {
168
+ const profile = await fetchBuilderProfileById(phid);
169
+ if (profile) {
170
+ result.set(phid, profile);
171
+ }
172
+ });
173
+ await Promise.all(directFetches);
174
+ }
175
+ return result;
176
+ }
177
+ catch {
178
+ return new Map();
179
+ }
180
+ }
package/dist/style.css CHANGED
@@ -8,6 +8,7 @@
8
8
  "Courier New", monospace;
9
9
  --color-red-50: oklch(97.1% 0.013 17.38);
10
10
  --color-red-100: hsl(3 82% 96%);
11
+ --color-red-300: hsl(6 82% 87%);
11
12
  --color-red-500: hsl(5 80% 78%);
12
13
  --color-red-600: hsl(4 81% 74%);
13
14
  --color-orange-500: hsl(33 99% 70%);
@@ -83,6 +84,7 @@
83
84
  --tracking-wider: 0.05em;
84
85
  --leading-relaxed: 1.625;
85
86
  --radius-sm: 0.25rem;
87
+ --radius-md: 0.375rem;
86
88
  --radius-lg: 0.5rem;
87
89
  --radius-xl: 0.75rem;
88
90
  --radius-2xl: 1rem;
@@ -293,6 +295,9 @@
293
295
  .mt-1 {
294
296
  margin-top: calc(var(--spacing) * 1);
295
297
  }
298
+ .mt-2 {
299
+ margin-top: calc(var(--spacing) * 2);
300
+ }
296
301
  .mt-3 {
297
302
  margin-top: calc(var(--spacing) * 3);
298
303
  }
@@ -329,6 +334,9 @@
329
334
  .inline-flex {
330
335
  display: inline-flex;
331
336
  }
337
+ .table {
338
+ display: table;
339
+ }
332
340
  .h-2 {
333
341
  height: calc(var(--spacing) * 2);
334
342
  }
@@ -398,6 +406,9 @@
398
406
  .flex-shrink-0 {
399
407
  flex-shrink: 0;
400
408
  }
409
+ .border-collapse {
410
+ border-collapse: collapse;
411
+ }
401
412
  .-translate-y-1\/2 {
402
413
  --tw-translate-y: calc(calc(1/2 * 100%) * -1);
403
414
  translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -414,6 +425,9 @@
414
425
  .grid-cols-1 {
415
426
  grid-template-columns: repeat(1, minmax(0, 1fr));
416
427
  }
428
+ .flex-col {
429
+ flex-direction: column;
430
+ }
417
431
  .flex-wrap {
418
432
  flex-wrap: wrap;
419
433
  }
@@ -492,6 +506,9 @@
492
506
  .rounded-lg {
493
507
  border-radius: var(--radius-lg);
494
508
  }
509
+ .rounded-md {
510
+ border-radius: var(--radius-md);
511
+ }
495
512
  .rounded-sm {
496
513
  border-radius: var(--radius-sm);
497
514
  }
@@ -533,6 +550,9 @@
533
550
  .border-indigo-100 {
534
551
  border-color: var(--color-indigo-100);
535
552
  }
553
+ .border-red-300 {
554
+ border-color: var(--color-red-300);
555
+ }
536
556
  .border-slate-100 {
537
557
  border-color: var(--color-slate-100);
538
558
  }
@@ -605,6 +625,9 @@
605
625
  .bg-purple-500 {
606
626
  background-color: var(--color-purple-500);
607
627
  }
628
+ .bg-red-50 {
629
+ background-color: var(--color-red-50);
630
+ }
608
631
  .bg-red-500 {
609
632
  background-color: var(--color-red-500);
610
633
  }
@@ -796,6 +819,10 @@
796
819
  font-size: var(--text-xs);
797
820
  line-height: var(--tw-leading, var(--text-xs--line-height));
798
821
  }
822
+ .leading-4 {
823
+ --tw-leading: calc(var(--spacing) * 4);
824
+ line-height: calc(var(--spacing) * 4);
825
+ }
799
826
  .leading-relaxed {
800
827
  --tw-leading: var(--leading-relaxed);
801
828
  line-height: var(--leading-relaxed);
@@ -863,6 +890,9 @@
863
890
  .text-red-500 {
864
891
  color: var(--color-red-500);
865
892
  }
893
+ .text-red-600 {
894
+ color: var(--color-red-600);
895
+ }
866
896
  .text-sky-700 {
867
897
  color: var(--color-sky-700);
868
898
  }
@@ -923,6 +953,10 @@
923
953
  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
924
954
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
925
955
  }
956
+ .blur {
957
+ --tw-blur: blur(8px);
958
+ filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
959
+ }
926
960
  .backdrop-blur-sm {
927
961
  --tw-backdrop-blur: blur(var(--blur-sm));
928
962
  -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
@@ -1304,6 +1338,59 @@
1304
1338
  inherits: false;
1305
1339
  initial-value: 0 0 #0000;
1306
1340
  }
1341
+ @property --tw-blur {
1342
+ syntax: "*";
1343
+ inherits: false;
1344
+ }
1345
+ @property --tw-brightness {
1346
+ syntax: "*";
1347
+ inherits: false;
1348
+ }
1349
+ @property --tw-contrast {
1350
+ syntax: "*";
1351
+ inherits: false;
1352
+ }
1353
+ @property --tw-grayscale {
1354
+ syntax: "*";
1355
+ inherits: false;
1356
+ }
1357
+ @property --tw-hue-rotate {
1358
+ syntax: "*";
1359
+ inherits: false;
1360
+ }
1361
+ @property --tw-invert {
1362
+ syntax: "*";
1363
+ inherits: false;
1364
+ }
1365
+ @property --tw-opacity {
1366
+ syntax: "*";
1367
+ inherits: false;
1368
+ }
1369
+ @property --tw-saturate {
1370
+ syntax: "*";
1371
+ inherits: false;
1372
+ }
1373
+ @property --tw-sepia {
1374
+ syntax: "*";
1375
+ inherits: false;
1376
+ }
1377
+ @property --tw-drop-shadow {
1378
+ syntax: "*";
1379
+ inherits: false;
1380
+ }
1381
+ @property --tw-drop-shadow-color {
1382
+ syntax: "*";
1383
+ inherits: false;
1384
+ }
1385
+ @property --tw-drop-shadow-alpha {
1386
+ syntax: "<percentage>";
1387
+ inherits: false;
1388
+ initial-value: 100%;
1389
+ }
1390
+ @property --tw-drop-shadow-size {
1391
+ syntax: "*";
1392
+ inherits: false;
1393
+ }
1307
1394
  @property --tw-backdrop-blur {
1308
1395
  syntax: "*";
1309
1396
  inherits: false;
@@ -1384,6 +1471,19 @@
1384
1471
  --tw-ring-offset-width: 0px;
1385
1472
  --tw-ring-offset-color: #fff;
1386
1473
  --tw-ring-offset-shadow: 0 0 #0000;
1474
+ --tw-blur: initial;
1475
+ --tw-brightness: initial;
1476
+ --tw-contrast: initial;
1477
+ --tw-grayscale: initial;
1478
+ --tw-hue-rotate: initial;
1479
+ --tw-invert: initial;
1480
+ --tw-opacity: initial;
1481
+ --tw-saturate: initial;
1482
+ --tw-sepia: initial;
1483
+ --tw-drop-shadow: initial;
1484
+ --tw-drop-shadow-color: initial;
1485
+ --tw-drop-shadow-alpha: 100%;
1486
+ --tw-drop-shadow-size: initial;
1387
1487
  --tw-backdrop-blur: initial;
1388
1488
  --tw-backdrop-brightness: initial;
1389
1489
  --tw-backdrop-contrast: initial;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@powerhousedao/builder-profile",
3
3
  "description": "Builder profile document model",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "files": [
@@ -65,12 +65,14 @@
65
65
  "@powerhousedao/builder-tools": "latest",
66
66
  "@powerhousedao/common": "latest",
67
67
  "@powerhousedao/design-system": "latest",
68
- "@powerhousedao/document-engineering": "^1.38.0",
68
+ "@powerhousedao/document-engineering": "^1.40.0",
69
+ "@uiw/react-md-editor": "^4.0.11",
69
70
  "document-model": "latest",
70
71
  "error": "^10.4.0",
71
72
  "graphql": "^16.10.0",
72
73
  "graphql-tag": "^2.12.6",
73
74
  "lucide-react": "^0.556.0",
75
+ "rehype-slug": "^6.0.0",
74
76
  "zod": "^3.24.2"
75
77
  },
76
78
  "devDependencies": {