@powerhousedao/contributor-billing 0.1.53 → 1.0.0-dev.10

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 (189) hide show
  1. package/dist/document-models/account-transactions/gen/schema/zod.d.ts.map +1 -1
  2. package/dist/document-models/account-transactions/gen/schema/zod.js +3 -3
  3. package/dist/document-models/account-transactions/module.d.ts +1 -1
  4. package/dist/document-models/account-transactions/module.d.ts.map +1 -1
  5. package/dist/document-models/account-transactions/module.js +1 -1
  6. package/dist/document-models/accounts/gen/schema/zod.d.ts.map +1 -1
  7. package/dist/document-models/accounts/module.d.ts +1 -1
  8. package/dist/document-models/accounts/module.d.ts.map +1 -1
  9. package/dist/document-models/accounts/module.js +1 -1
  10. package/dist/document-models/billing-statement/gen/schema/zod.d.ts.map +1 -1
  11. package/dist/document-models/billing-statement/gen/schema/zod.js +4 -4
  12. package/dist/document-models/billing-statement/module.d.ts +1 -1
  13. package/dist/document-models/billing-statement/module.d.ts.map +1 -1
  14. package/dist/document-models/billing-statement/module.js +1 -1
  15. package/dist/document-models/expense-report/gen/schema/zod.d.ts.map +1 -1
  16. package/dist/document-models/expense-report/gen/schema/zod.js +38 -18
  17. package/dist/document-models/expense-report/module.d.ts +1 -1
  18. package/dist/document-models/expense-report/module.d.ts.map +1 -1
  19. package/dist/document-models/expense-report/module.js +1 -1
  20. package/dist/document-models/invoice/gen/document-model.d.ts.map +1 -1
  21. package/dist/document-models/invoice/gen/document-model.js +150 -150
  22. package/dist/document-models/invoice/gen/schema/types.d.ts +3 -6
  23. package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -1
  24. package/dist/document-models/invoice/gen/schema/zod.d.ts +2 -8
  25. package/dist/document-models/invoice/gen/schema/zod.d.ts.map +1 -1
  26. package/dist/document-models/invoice/gen/schema/zod.js +14 -25
  27. package/dist/document-models/invoice/module.d.ts +1 -1
  28. package/dist/document-models/invoice/module.d.ts.map +1 -1
  29. package/dist/document-models/invoice/module.js +1 -1
  30. package/dist/document-models/invoice/src/reducers/general.d.ts.map +1 -1
  31. package/dist/document-models/invoice/src/reducers/general.js +8 -0
  32. package/dist/document-models/invoice/src/reducers/items.d.ts.map +1 -1
  33. package/dist/document-models/invoice/src/reducers/items.js +2 -1
  34. package/dist/document-models/invoice/src/reducers/parties.d.ts.map +1 -1
  35. package/dist/document-models/invoice/src/reducers/parties.js +6 -2
  36. package/dist/document-models/invoice/src/reducers/transitions.d.ts +0 -5
  37. package/dist/document-models/invoice/src/reducers/transitions.d.ts.map +1 -1
  38. package/dist/document-models/invoice/src/reducers/transitions.js +19 -6
  39. package/dist/document-models/invoice/tests/general.test.js +11 -2
  40. package/dist/document-models/invoice/tests/items.test.js +1 -1
  41. package/dist/document-models/invoice/tests/parties.test.js +1 -1
  42. package/dist/document-models/invoice/tests/transitions.test.js +7 -2
  43. package/dist/document-models/operational-hub-profile/module.d.ts +1 -1
  44. package/dist/document-models/operational-hub-profile/module.d.ts.map +1 -1
  45. package/dist/document-models/operational-hub-profile/module.js +1 -1
  46. package/dist/document-models/snapshot-report/gen/schema/zod.d.ts.map +1 -1
  47. package/dist/document-models/snapshot-report/gen/schema/zod.js +12 -12
  48. package/dist/document-models/snapshot-report/module.d.ts +1 -1
  49. package/dist/document-models/snapshot-report/module.d.ts.map +1 -1
  50. package/dist/document-models/snapshot-report/module.js +1 -1
  51. package/dist/editors/accounts-editor/editor.d.ts.map +1 -1
  52. package/dist/editors/accounts-editor/editor.js +2 -2
  53. package/dist/editors/builder-team-admin/components/DriveExplorer.d.ts.map +1 -1
  54. package/dist/editors/builder-team-admin/components/DriveExplorer.js +64 -4
  55. package/dist/editors/builder-team-admin/module.js +1 -1
  56. package/dist/editors/contributor-billing/components/DashboardHome.d.ts.map +1 -1
  57. package/dist/editors/contributor-billing/components/DashboardHome.js +2 -8
  58. package/dist/editors/contributor-billing/components/DocumentDropZone.d.ts.map +1 -1
  59. package/dist/editors/contributor-billing/components/DocumentDropZone.js +37 -8
  60. package/dist/editors/contributor-billing/components/DriveContents.d.ts.map +1 -1
  61. package/dist/editors/contributor-billing/components/DriveContents.js +4 -1
  62. package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
  63. package/dist/editors/contributor-billing/components/DriveExplorer.js +54 -3
  64. package/dist/editors/contributor-billing/components/FolderTree.d.ts.map +1 -1
  65. package/dist/editors/contributor-billing/components/FolderTree.js +6 -15
  66. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +2 -1
  67. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
  68. package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +41 -6
  69. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +1 -1
  70. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
  71. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +16 -1
  72. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts +3 -1
  73. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.d.ts.map +1 -1
  74. package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableContainer.js +13 -11
  75. package/dist/editors/contributor-billing/components/MonthReportCard.d.ts +11 -4
  76. package/dist/editors/contributor-billing/components/MonthReportCard.d.ts.map +1 -1
  77. package/dist/editors/contributor-billing/components/MonthReportCard.js +55 -6
  78. package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts +1 -1
  79. package/dist/editors/contributor-billing/components/MonthlyReportsOverview.d.ts.map +1 -1
  80. package/dist/editors/contributor-billing/components/MonthlyReportsOverview.js +104 -7
  81. package/dist/editors/contributor-billing/components/ReportingView.d.ts +0 -3
  82. package/dist/editors/contributor-billing/components/ReportingView.d.ts.map +1 -1
  83. package/dist/editors/contributor-billing/components/ReportingView.js +65 -8
  84. package/dist/editors/contributor-billing/components/ToastRenderer.d.ts +2 -0
  85. package/dist/editors/contributor-billing/components/ToastRenderer.d.ts.map +1 -0
  86. package/dist/editors/contributor-billing/components/ToastRenderer.js +14 -0
  87. package/dist/editors/contributor-billing/components/cbToast.d.ts +16 -0
  88. package/dist/editors/contributor-billing/components/cbToast.d.ts.map +1 -0
  89. package/dist/editors/contributor-billing/components/cbToast.js +29 -0
  90. package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.d.ts.map +1 -1
  91. package/dist/editors/contributor-billing/hooks/useDocumentAutoPlacement.js +42 -2
  92. package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts +4 -0
  93. package/dist/editors/contributor-billing/hooks/useMonthlyReports.d.ts.map +1 -1
  94. package/dist/editors/contributor-billing/hooks/useMonthlyReports.js +4 -0
  95. package/dist/editors/contributor-billing/module.js +1 -1
  96. package/dist/editors/invoice/InvoicePDF.d.ts.map +1 -1
  97. package/dist/editors/invoice/InvoicePDF.js +12 -9
  98. package/dist/editors/invoice/editor.d.ts.map +1 -1
  99. package/dist/editors/invoice/editor.js +6 -10
  100. package/dist/editors/invoice/exportUBL.d.ts.map +1 -1
  101. package/dist/editors/invoice/exportUBL.js +1 -2
  102. package/dist/editors/invoice/ingestPDF.js +1 -1
  103. package/dist/editors/invoice/invoiceToGnosis.d.ts.map +1 -1
  104. package/dist/editors/invoice/invoiceToGnosis.js +25 -22
  105. package/dist/editors/invoice/invoiceToast.d.ts +4 -0
  106. package/dist/editors/invoice/invoiceToast.d.ts.map +1 -0
  107. package/dist/editors/invoice/invoiceToast.js +6 -0
  108. package/dist/editors/invoice/legalEntity/legalEntity.d.ts +2 -1
  109. package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -1
  110. package/dist/editors/invoice/legalEntity/legalEntity.js +3 -14
  111. package/dist/editors/invoice/legalEntity/walletSection.d.ts +1 -0
  112. package/dist/editors/invoice/legalEntity/walletSection.d.ts.map +1 -1
  113. package/dist/editors/invoice/legalEntity/walletSection.js +2 -2
  114. package/dist/editors/invoice/lineItems.js +1 -1
  115. package/dist/editors/invoice/requestFinance.d.ts +3 -2
  116. package/dist/editors/invoice/requestFinance.d.ts.map +1 -1
  117. package/dist/editors/invoice/requestFinance.js +38 -42
  118. package/dist/editors/invoice/validation/validationHandler.d.ts +1 -1
  119. package/dist/editors/invoice/validation/validationHandler.d.ts.map +1 -1
  120. package/dist/editors/invoice/validation/validationHandler.js +15 -2
  121. package/dist/editors/invoice/validation/validationManager.d.ts +1 -1
  122. package/dist/editors/invoice/validation/validationManager.d.ts.map +1 -1
  123. package/dist/editors/invoice/validation/validationManager.js +2 -1
  124. package/dist/editors/invoice/validation/validationRules.d.ts +1 -0
  125. package/dist/editors/invoice/validation/validationRules.d.ts.map +1 -1
  126. package/dist/editors/invoice/validation/validationRules.js +26 -1
  127. package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts +19 -0
  128. package/dist/editors/snapshot-report-editor/components/DateRangePicker.d.ts.map +1 -0
  129. package/dist/editors/snapshot-report-editor/components/DateRangePicker.js +66 -0
  130. package/dist/editors/snapshot-report-editor/editor.d.ts.map +1 -1
  131. package/dist/editors/snapshot-report-editor/editor.js +72 -48
  132. package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts +33 -0
  133. package/dist/scripts/download-all-drive-documents/download-drive-documents.d.ts.map +1 -0
  134. package/dist/scripts/download-all-drive-documents/download-drive-documents.js +583 -0
  135. package/dist/scripts/invoice/requestFinance.d.ts +18 -1
  136. package/dist/scripts/invoice/requestFinance.d.ts.map +1 -1
  137. package/dist/scripts/invoice/requestFinance.js +17 -5
  138. package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts +20 -0
  139. package/dist/scripts/upload-phd-documents/upload-phd-documents.d.ts.map +1 -0
  140. package/dist/scripts/upload-phd-documents/upload-phd-documents.js +313 -0
  141. package/dist/style.css +201 -106
  142. package/dist/subgraphs/budget-statements/resolvers.d.ts +38 -0
  143. package/dist/subgraphs/budget-statements/resolvers.d.ts.map +1 -1
  144. package/dist/subgraphs/budget-statements/resolvers.js +192 -62
  145. package/dist/subgraphs/budget-statements/resolvers.test.d.ts +2 -0
  146. package/dist/subgraphs/budget-statements/resolvers.test.d.ts.map +1 -0
  147. package/dist/subgraphs/budget-statements/resolvers.test.js +339 -0
  148. package/dist/subgraphs/budget-statements/schema.d.ts.map +1 -1
  149. package/dist/subgraphs/budget-statements/schema.js +8 -0
  150. package/dist/subgraphs/index.d.ts +0 -1
  151. package/dist/subgraphs/index.d.ts.map +1 -1
  152. package/dist/subgraphs/index.js +0 -1
  153. package/dist/subgraphs/invoice-addon/customResolvers.d.ts +70 -11
  154. package/dist/subgraphs/invoice-addon/customResolvers.d.ts.map +1 -1
  155. package/dist/subgraphs/invoice-addon/customResolvers.js +12 -27
  156. package/package.json +35 -28
  157. package/dist/document-models/invoice/src/tests/document-model.test.d.ts +0 -10
  158. package/dist/document-models/invoice/src/tests/document-model.test.d.ts.map +0 -1
  159. package/dist/document-models/invoice/src/tests/document-model.test.js +0 -104
  160. package/dist/document-models/invoice/src/tests/general.test.d.ts +0 -6
  161. package/dist/document-models/invoice/src/tests/general.test.d.ts.map +0 -1
  162. package/dist/document-models/invoice/src/tests/general.test.js +0 -49
  163. package/dist/document-models/invoice/src/tests/items.test.d.ts +0 -6
  164. package/dist/document-models/invoice/src/tests/items.test.d.ts.map +0 -1
  165. package/dist/document-models/invoice/src/tests/items.test.js +0 -59
  166. package/dist/document-models/invoice/src/tests/parties.test.d.ts +0 -6
  167. package/dist/document-models/invoice/src/tests/parties.test.d.ts.map +0 -1
  168. package/dist/document-models/invoice/src/tests/parties.test.js +0 -69
  169. package/dist/document-models/invoice/src/tests/transitions.test.d.ts +0 -6
  170. package/dist/document-models/invoice/src/tests/transitions.test.d.ts.map +0 -1
  171. package/dist/document-models/invoice/src/tests/transitions.test.js +0 -59
  172. package/dist/document-models/invoice/utils/statusTransitions.d.ts +0 -13
  173. package/dist/document-models/invoice/utils/statusTransitions.d.ts.map +0 -1
  174. package/dist/document-models/invoice/utils/statusTransitions.js +0 -13
  175. package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts +0 -15
  176. package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.d.ts.map +0 -1
  177. package/dist/editors/builder-team-admin/components/overview/SubscriptionsStats.js +0 -61
  178. package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts +0 -12
  179. package/dist/editors/contributor-billing/components/CreateHubProfileModal.d.ts.map +0 -1
  180. package/dist/editors/contributor-billing/components/CreateHubProfileModal.js +0 -74
  181. package/dist/subgraphs/resources-services/index.d.ts +0 -11
  182. package/dist/subgraphs/resources-services/index.d.ts.map +0 -1
  183. package/dist/subgraphs/resources-services/index.js +0 -11
  184. package/dist/subgraphs/resources-services/resolvers.d.ts +0 -3
  185. package/dist/subgraphs/resources-services/resolvers.d.ts.map +0 -1
  186. package/dist/subgraphs/resources-services/resolvers.js +0 -462
  187. package/dist/subgraphs/resources-services/schema.d.ts +0 -3
  188. package/dist/subgraphs/resources-services/schema.d.ts.map +0 -1
  189. package/dist/subgraphs/resources-services/schema.js +0 -284
@@ -0,0 +1,583 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Download all documents from a Powerhouse switchboard as .phd files.
4
+ *
5
+ * REQUIRES: Bun runtime (https://bun.sh) — Node.js is NOT supported.
6
+ *
7
+ * Usage:
8
+ * bun scripts/download-drive-documents.ts <switchboard-url> [drive-id]
9
+ *
10
+ * Examples:
11
+ * # Download all documents from all drives
12
+ * bun scripts/download-drive-documents.ts https://switchboard-dev.powerhouse.xyz
13
+ *
14
+ * # Download documents from a specific drive
15
+ * bun scripts/download-drive-documents.ts https://switchboard-dev.powerhouse.xyz layer-resources-drive
16
+ *
17
+ * Output structure:
18
+ * ./downloads/<drive-name>/
19
+ * ├── document-a.phd
20
+ * ├── FolderName/
21
+ * │ └── document-b.phd
22
+ * └── ...
23
+ *
24
+ * The .phd files are ZIP archives containing:
25
+ * - header.json — document metadata (id, type, timestamps)
26
+ * - state.json — initial empty state
27
+ * - current-state.json — current document state
28
+ * - operations.json — operation history (global scope)
29
+ *
30
+ * No external dependencies required — uses only Node.js built-in modules.
31
+ */
32
+ import { deflateRawSync, inflateRawSync } from "node:zlib";
33
+ import fs from "node:fs";
34
+ import path from "node:path";
35
+ // ---------------------------------------------------------------------------
36
+ // Minimal ZIP implementation (DEFLATE, no external deps)
37
+ // ---------------------------------------------------------------------------
38
+ function crc32(buf) {
39
+ // Standard CRC-32 lookup table
40
+ const table = new Uint32Array(256);
41
+ for (let i = 0; i < 256; i++) {
42
+ let c = i;
43
+ for (let j = 0; j < 8; j++) {
44
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
45
+ }
46
+ table[i] = c;
47
+ }
48
+ let crc = 0xffffffff;
49
+ for (let i = 0; i < buf.length; i++) {
50
+ crc = table[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
51
+ }
52
+ return (crc ^ 0xffffffff) >>> 0;
53
+ }
54
+ function createZipBuffer(files) {
55
+ const entries = [];
56
+ let offset = 0;
57
+ const localHeaders = [];
58
+ for (const [name, content] of files) {
59
+ const nameBytes = Buffer.from(name, "utf-8");
60
+ const data = Buffer.from(content, "utf-8");
61
+ const compressed = deflateRawSync(data);
62
+ const crc = crc32(data);
63
+ // Local file header (30 bytes + name + compressed data)
64
+ const local = Buffer.alloc(30);
65
+ local.writeUInt32LE(0x04034b50, 0); // signature
66
+ local.writeUInt16LE(20, 4); // version needed
67
+ local.writeUInt16LE(0, 6); // flags
68
+ local.writeUInt16LE(8, 8); // compression: DEFLATE
69
+ local.writeUInt16LE(0, 10); // mod time
70
+ local.writeUInt16LE(0, 12); // mod date
71
+ local.writeUInt32LE(crc, 14); // crc-32
72
+ local.writeUInt32LE(compressed.length, 18); // compressed size
73
+ local.writeUInt32LE(data.length, 22); // uncompressed size
74
+ local.writeUInt16LE(nameBytes.length, 26); // filename length
75
+ local.writeUInt16LE(0, 28); // extra length
76
+ entries.push({ name: nameBytes, data, compressed, crc, offset });
77
+ localHeaders.push(local, nameBytes, compressed);
78
+ offset += 30 + nameBytes.length + compressed.length;
79
+ }
80
+ // Central directory
81
+ const centralDir = [];
82
+ let centralSize = 0;
83
+ const centralOffset = offset;
84
+ for (const entry of entries) {
85
+ const central = Buffer.alloc(46);
86
+ central.writeUInt32LE(0x02014b50, 0); // signature
87
+ central.writeUInt16LE(20, 4); // version made by
88
+ central.writeUInt16LE(20, 6); // version needed
89
+ central.writeUInt16LE(0, 8); // flags
90
+ central.writeUInt16LE(8, 10); // compression: DEFLATE
91
+ central.writeUInt16LE(0, 12); // mod time
92
+ central.writeUInt16LE(0, 14); // mod date
93
+ central.writeUInt32LE(entry.crc, 16); // crc-32
94
+ central.writeUInt32LE(entry.compressed.length, 20); // compressed size
95
+ central.writeUInt32LE(entry.data.length, 24); // uncompressed size
96
+ central.writeUInt16LE(entry.name.length, 28); // filename length
97
+ central.writeUInt16LE(0, 30); // extra length
98
+ central.writeUInt16LE(0, 32); // comment length
99
+ central.writeUInt16LE(0, 34); // disk start
100
+ central.writeUInt16LE(0, 36); // internal attrs
101
+ central.writeUInt32LE(0, 38); // external attrs
102
+ central.writeUInt32LE(entry.offset, 42); // local header offset
103
+ centralDir.push(central, entry.name);
104
+ centralSize += 46 + entry.name.length;
105
+ }
106
+ // End of central directory
107
+ const eocd = Buffer.alloc(22);
108
+ eocd.writeUInt32LE(0x06054b50, 0); // signature
109
+ eocd.writeUInt16LE(0, 4); // disk number
110
+ eocd.writeUInt16LE(0, 6); // start disk
111
+ eocd.writeUInt16LE(entries.length, 8); // entries on disk
112
+ eocd.writeUInt16LE(entries.length, 10); // total entries
113
+ eocd.writeUInt32LE(centralSize, 12); // central dir size
114
+ eocd.writeUInt32LE(centralOffset, 16); // central dir offset
115
+ eocd.writeUInt16LE(0, 20); // comment length
116
+ return Buffer.concat([...localHeaders, ...centralDir, eocd]);
117
+ }
118
+ /**
119
+ * Read a single file entry from a ZIP buffer by name.
120
+ * Returns the decompressed content as a Buffer, or null if not found.
121
+ */
122
+ function readZipEntry(zipBuf, entryName) {
123
+ let offset = 0;
124
+ while (offset + 30 <= zipBuf.length) {
125
+ const sig = zipBuf.readUInt32LE(offset);
126
+ if (sig !== 0x04034b50)
127
+ break; // not a local file header
128
+ const compressionMethod = zipBuf.readUInt16LE(offset + 8);
129
+ const compressedSize = zipBuf.readUInt32LE(offset + 18);
130
+ const nameLen = zipBuf.readUInt16LE(offset + 26);
131
+ const extraLen = zipBuf.readUInt16LE(offset + 28);
132
+ const nameStart = offset + 30;
133
+ const name = zipBuf
134
+ .subarray(nameStart, nameStart + nameLen)
135
+ .toString("utf-8");
136
+ const dataStart = nameStart + nameLen + extraLen;
137
+ const dataEnd = dataStart + compressedSize;
138
+ if (name === entryName) {
139
+ const raw = zipBuf.subarray(dataStart, dataEnd);
140
+ if (compressionMethod === 8) {
141
+ // DEFLATE
142
+ return Buffer.from(inflateRawSync(raw));
143
+ }
144
+ // stored (method 0) — return as-is
145
+ return Buffer.from(raw);
146
+ }
147
+ offset = dataEnd;
148
+ }
149
+ return null;
150
+ }
151
+ function verifyPhdFile(filePath, expectedStateJSON) {
152
+ const zipBuf = fs.readFileSync(filePath);
153
+ const currentStateBuf = readZipEntry(zipBuf, "current-state.json");
154
+ if (!currentStateBuf) {
155
+ return { valid: false, reason: "current-state.json not found in .phd" };
156
+ }
157
+ let savedState;
158
+ try {
159
+ savedState = JSON.parse(currentStateBuf.toString("utf-8"));
160
+ }
161
+ catch {
162
+ return { valid: false, reason: "Failed to parse current-state.json" };
163
+ }
164
+ const savedGlobal = JSON.stringify(savedState.global ?? {});
165
+ const expectedGlobal = JSON.stringify(expectedStateJSON ?? {});
166
+ if (savedGlobal === expectedGlobal) {
167
+ return { valid: true };
168
+ }
169
+ return {
170
+ valid: false,
171
+ reason: `State mismatch — saved global has ${savedGlobal.length} chars, API stateJSON has ${expectedGlobal.length} chars`,
172
+ };
173
+ }
174
+ // ---------------------------------------------------------------------------
175
+ // Helpers
176
+ // ---------------------------------------------------------------------------
177
+ const REQUEST_DELAY_MS = 300;
178
+ function sleep(ms) {
179
+ return new Promise((resolve) => setTimeout(resolve, ms));
180
+ }
181
+ /**
182
+ * Normalize the base URL: strip trailing slashes and common suffixes like
183
+ * "/graphql" so that both "https://sb.xyz" and "https://sb.xyz/graphql" work.
184
+ */
185
+ function normalizeBaseUrl(raw) {
186
+ return raw.replace(/\/+$/, "").replace(/\/graphql$/i, "");
187
+ }
188
+ async function gqlQuery(endpoint, query, variables) {
189
+ const res = await fetch(endpoint, {
190
+ method: "POST",
191
+ headers: { "Content-Type": "application/json" },
192
+ body: JSON.stringify({ query, variables }),
193
+ });
194
+ if (!res.ok) {
195
+ let body = "";
196
+ try {
197
+ body = await res.text();
198
+ }
199
+ catch {
200
+ /* ignore */
201
+ }
202
+ const detail = body ? `\n Response: ${body.slice(0, 500)}` : "";
203
+ throw new Error(`GraphQL request failed: ${res.status} ${res.statusText} (${endpoint})${detail}`);
204
+ }
205
+ const json = (await res.json());
206
+ if (json.errors?.length) {
207
+ throw new Error(`GraphQL errors:\n${json.errors.map((e) => ` - ${e.message}`).join("\n")}`);
208
+ }
209
+ if (!json.data) {
210
+ throw new Error("No data returned from GraphQL query");
211
+ }
212
+ return json.data;
213
+ }
214
+ // ---------------------------------------------------------------------------
215
+ // API calls
216
+ // ---------------------------------------------------------------------------
217
+ async function fetchDrives(baseUrl) {
218
+ const data = await gqlQuery(`${baseUrl}/graphql`, `{ drives }`);
219
+ return data.drives;
220
+ }
221
+ async function fetchDriveInfo(baseUrl, driveId) {
222
+ const data = await gqlQuery(`${baseUrl}/d/${driveId}`, `{
223
+ drive { id name slug icon }
224
+ driveDocument {
225
+ state {
226
+ name icon
227
+ nodes {
228
+ ... on DocumentDrive_FileNode {
229
+ id name kind documentType parentFolder
230
+ }
231
+ ... on DocumentDrive_FolderNode {
232
+ id name kind parentFolder
233
+ }
234
+ }
235
+ }
236
+ }
237
+ }`);
238
+ return {
239
+ drive: data.drive,
240
+ nodes: data.driveDocument.state.nodes,
241
+ };
242
+ }
243
+ async function fetchDocument(baseUrl, driveId, docId) {
244
+ // First fetch document metadata + stateJSON + first batch of operations
245
+ const BATCH_SIZE = 100;
246
+ const data = await gqlQuery(`${baseUrl}/d/${driveId}`, `query ($id: String!, $first: Int, $skip: Int) {
247
+ document(id: $id) {
248
+ id name documentType revision
249
+ createdAtUtcIso lastModifiedAtUtcIso
250
+ operations(first: $first, skip: $skip) {
251
+ id type index timestampUtcMs hash skip inputText error
252
+ }
253
+ stateJSON
254
+ }
255
+ }`, { id: docId, first: BATCH_SIZE, skip: 0 });
256
+ const doc = data.document;
257
+ const allOps = [...doc.operations];
258
+ // Paginate through remaining operations if first batch was full
259
+ while (allOps.length > 0 && allOps.length % BATCH_SIZE === 0) {
260
+ await sleep(REQUEST_DELAY_MS);
261
+ const moreData = await gqlQuery(`${baseUrl}/d/${driveId}`, `query ($id: String!, $first: Int, $skip: Int) {
262
+ document(id: $id) {
263
+ operations(first: $first, skip: $skip) {
264
+ id type index timestampUtcMs hash skip inputText error
265
+ }
266
+ }
267
+ }`, { id: docId, first: BATCH_SIZE, skip: allOps.length });
268
+ const batch = moreData.document.operations;
269
+ if (batch.length === 0)
270
+ break;
271
+ allOps.push(...batch);
272
+ }
273
+ doc.operations = allOps;
274
+ return doc;
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // Folder path resolution
278
+ // ---------------------------------------------------------------------------
279
+ function buildFolderPaths(nodes) {
280
+ const folders = nodes.filter((n) => n.kind === "folder");
281
+ const folderMap = new Map();
282
+ for (const f of folders) {
283
+ folderMap.set(f.id, f);
284
+ }
285
+ const pathCache = new Map();
286
+ function resolve(folderId) {
287
+ if (pathCache.has(folderId))
288
+ return pathCache.get(folderId);
289
+ const folder = folderMap.get(folderId);
290
+ if (!folder)
291
+ return "";
292
+ const parentPath = folder.parentFolder ? resolve(folder.parentFolder) : "";
293
+ const fullPath = parentPath
294
+ ? path.join(parentPath, sanitize(folder.name))
295
+ : sanitize(folder.name);
296
+ pathCache.set(folderId, fullPath);
297
+ return fullPath;
298
+ }
299
+ for (const f of folders) {
300
+ resolve(f.id);
301
+ }
302
+ return pathCache;
303
+ }
304
+ function getNodePath(node, folderPaths) {
305
+ if (!node.parentFolder)
306
+ return "";
307
+ return folderPaths.get(node.parentFolder) ?? "";
308
+ }
309
+ function sanitize(name) {
310
+ return name.replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").trim() || "unnamed";
311
+ }
312
+ // ---------------------------------------------------------------------------
313
+ // .phd file creation
314
+ // ---------------------------------------------------------------------------
315
+ function gqlOperationToInternal(op, scope) {
316
+ let input = {};
317
+ if (op.inputText) {
318
+ try {
319
+ input = JSON.parse(op.inputText);
320
+ }
321
+ catch {
322
+ input = op.inputText;
323
+ }
324
+ }
325
+ return {
326
+ id: op.id,
327
+ index: op.index,
328
+ skip: op.skip ?? 0,
329
+ hash: op.hash,
330
+ timestampUtcMs: op.timestampUtcMs,
331
+ error: op.error ?? undefined,
332
+ action: {
333
+ id: op.id,
334
+ type: op.type,
335
+ timestampUtcMs: op.timestampUtcMs,
336
+ input,
337
+ scope,
338
+ },
339
+ };
340
+ }
341
+ function createPhdFile(doc) {
342
+ const header = {
343
+ id: doc.id,
344
+ sig: { publicKey: {}, nonce: "" },
345
+ documentType: doc.documentType,
346
+ createdAtUtcIso: doc.createdAtUtcIso,
347
+ slug: doc.id,
348
+ name: doc.name,
349
+ branch: "main",
350
+ revision: { global: doc.revision },
351
+ lastModifiedAtUtcIso: doc.lastModifiedAtUtcIso,
352
+ meta: {},
353
+ };
354
+ const initialState = {
355
+ auth: {},
356
+ document: {
357
+ version: 0,
358
+ hash: { algorithm: "sha1", encoding: "base64" },
359
+ },
360
+ global: {},
361
+ local: {},
362
+ };
363
+ const currentState = {
364
+ auth: {},
365
+ document: {
366
+ version: 0,
367
+ hash: { algorithm: "sha1", encoding: "base64" },
368
+ },
369
+ global: doc.stateJSON ?? {},
370
+ local: {},
371
+ };
372
+ const operations = {
373
+ global: doc.operations.map((op) => gqlOperationToInternal(op, "global")),
374
+ };
375
+ const files = new Map();
376
+ files.set("header.json", JSON.stringify(header, null, 2));
377
+ files.set("state.json", JSON.stringify(initialState, null, 2));
378
+ files.set("current-state.json", JSON.stringify(currentState, null, 2));
379
+ files.set("operations.json", JSON.stringify(operations, null, 2));
380
+ return createZipBuffer(files);
381
+ }
382
+ // ---------------------------------------------------------------------------
383
+ // Main
384
+ // ---------------------------------------------------------------------------
385
+ async function downloadDrive(baseUrl, driveId, outputBase) {
386
+ console.log(`\n${"=".repeat(60)}`);
387
+ console.log(`DRIVE: ${driveId}`);
388
+ console.log(`${"=".repeat(60)}`);
389
+ console.log(` Endpoint: ${baseUrl}/d/${driveId}`);
390
+ console.log(` Fetching drive info...`);
391
+ const { drive, nodes } = await fetchDriveInfo(baseUrl, driveId);
392
+ const driveName = sanitize(drive.name || driveId);
393
+ const driveDir = path.join(outputBase, driveName);
394
+ console.log(` Name: ${drive.name}`);
395
+ console.log(` Slug: ${drive.slug}`);
396
+ console.log(` Icon: ${drive.icon ?? "(none)"}`);
397
+ const folders = nodes.filter((n) => n.kind === "folder");
398
+ const files = nodes.filter((n) => "documentType" in n && n.kind === "file");
399
+ console.log(` Nodes: ${nodes.length} total (${files.length} files, ${folders.length} folders)`);
400
+ if (folders.length > 0) {
401
+ console.log(` Folders:`);
402
+ const folderPaths = buildFolderPaths(nodes);
403
+ for (const folder of folders) {
404
+ const resolvedPath = folderPaths.get(folder.id) ?? folder.name;
405
+ const parent = folder.parentFolder
406
+ ? ` (parent: ${folder.parentFolder})`
407
+ : " (root)";
408
+ console.log(` /${resolvedPath}${parent}`);
409
+ }
410
+ // Create folder structure
411
+ for (const folderPath of folderPaths.values()) {
412
+ fs.mkdirSync(path.join(driveDir, folderPath), { recursive: true });
413
+ }
414
+ }
415
+ // Build a map of document ID -> file node for name/path resolution
416
+ const fileNodes = new Map();
417
+ for (const node of nodes) {
418
+ if ("documentType" in node && node.kind === "file") {
419
+ fileNodes.set(node.id, node);
420
+ }
421
+ }
422
+ if (files.length > 0) {
423
+ console.log(` Files:`);
424
+ for (const file of files) {
425
+ const folderPaths = buildFolderPaths(nodes);
426
+ const filePath = file.parentFolder
427
+ ? `${folderPaths.get(file.parentFolder) ?? ""}/${file.name}`
428
+ : file.name;
429
+ console.log(` ${file.id} -> /${filePath} (${file.documentType})`);
430
+ }
431
+ }
432
+ const docIds = [...fileNodes.keys()];
433
+ console.log(`\n Downloading ${docIds.length} documents...`);
434
+ let saved = 0;
435
+ let failed = 0;
436
+ let verified = 0;
437
+ let verifyFailed = 0;
438
+ let emptyState = 0;
439
+ const failures = [];
440
+ const verifyFailures = [];
441
+ const emptyStateIds = [];
442
+ for (const docId of docIds) {
443
+ const fileNode = fileNodes.get(docId);
444
+ const nodeName = fileNode?.name ?? docId;
445
+ try {
446
+ if (saved + failed > 0)
447
+ await sleep(REQUEST_DELAY_MS);
448
+ console.log(` [${saved + failed + 1}/${docIds.length}] Fetching "${nodeName}" (${docId})...`);
449
+ const doc = await fetchDocument(baseUrl, driveId, docId);
450
+ // Warn about empty stateJSON
451
+ const stateIsEmpty = doc.stateJSON == null ||
452
+ (typeof doc.stateJSON === "object" &&
453
+ Object.keys(doc.stateJSON).length === 0);
454
+ if (stateIsEmpty) {
455
+ emptyState++;
456
+ emptyStateIds.push({
457
+ id: docId,
458
+ name: nodeName,
459
+ documentType: doc.documentType,
460
+ });
461
+ console.warn(` WARNING: stateJSON is empty for "${nodeName}" (${doc.documentType})` +
462
+ ` — the downloaded .phd will have an empty global state`);
463
+ }
464
+ const folderPaths = buildFolderPaths(nodes);
465
+ const subDir = fileNode ? getNodePath(fileNode, folderPaths) : "";
466
+ const docName = sanitize(doc.name || docId);
467
+ const fileName = `${docName}.phd`;
468
+ const fullDir = path.join(driveDir, subDir);
469
+ const filePath = path.join(fullDir, fileName);
470
+ fs.mkdirSync(fullDir, { recursive: true });
471
+ const data = createPhdFile(doc);
472
+ fs.writeFileSync(filePath, data);
473
+ const relativePath = path.relative(outputBase, filePath);
474
+ const sizeKb = (data.length / 1024).toFixed(1);
475
+ const opsCount = doc.operations.length;
476
+ console.log(` Saved ${relativePath} (${doc.documentType}, ${opsCount} ops, ${sizeKb} KB)`);
477
+ // Post-save verification: read back the .phd and compare state
478
+ const vResult = verifyPhdFile(filePath, doc.stateJSON);
479
+ if (vResult.valid) {
480
+ verified++;
481
+ console.log(` Verified OK`);
482
+ }
483
+ else {
484
+ verifyFailed++;
485
+ verifyFailures.push({
486
+ id: docId,
487
+ name: nodeName,
488
+ reason: vResult.reason,
489
+ });
490
+ console.warn(` VERIFY FAILED: ${vResult.reason}`);
491
+ }
492
+ saved++;
493
+ }
494
+ catch (err) {
495
+ const reason = err instanceof Error ? err.message : String(err);
496
+ console.error(` SKIP "${nodeName}": ${reason}`);
497
+ failures.push({ id: docId, name: nodeName, reason });
498
+ failed++;
499
+ }
500
+ }
501
+ console.log(`\n Summary for "${drive.name}":`);
502
+ console.log(` Saved: ${saved}`);
503
+ console.log(` Skipped: ${failed}`);
504
+ console.log(` Verified OK: ${verified}`);
505
+ console.log(` Verify failed: ${verifyFailed}`);
506
+ console.log(` Empty stateJSON: ${emptyState}`);
507
+ if (failures.length > 0) {
508
+ console.log(` Reasons for skipped documents:`);
509
+ for (const f of failures) {
510
+ console.log(` - "${f.name}" (${f.id})`);
511
+ console.log(` ${f.reason}`);
512
+ }
513
+ }
514
+ if (verifyFailures.length > 0) {
515
+ console.log(` Verification failures:`);
516
+ for (const f of verifyFailures) {
517
+ console.log(` - "${f.name}" (${f.id})`);
518
+ console.log(` ${f.reason}`);
519
+ }
520
+ }
521
+ if (emptyStateIds.length > 0) {
522
+ console.log(` Documents with empty stateJSON:`);
523
+ for (const d of emptyStateIds) {
524
+ console.log(` - "${d.name}" (${d.id}) [${d.documentType}]`);
525
+ }
526
+ }
527
+ }
528
+ async function main() {
529
+ const args = process.argv.slice(2);
530
+ if (args.length === 0) {
531
+ console.log("Usage: bun scripts/download-drive-documents.ts <switchboard-url> [drive-id]");
532
+ console.log("\nExamples:");
533
+ console.log(" bun scripts/download-drive-documents.ts https://switchboard-dev.powerhouse.xyz");
534
+ console.log(" bun scripts/download-drive-documents.ts https://switchboard-dev.powerhouse.xyz layer-resources-drive");
535
+ process.exit(1);
536
+ }
537
+ const baseUrl = normalizeBaseUrl(args[0]);
538
+ const driveIdArg = args[1];
539
+ const outputBase = path.resolve("./downloads");
540
+ console.log(`Switchboard: ${baseUrl}`);
541
+ console.log(`Output dir: ${outputBase}`);
542
+ console.log(`\nFetching drive list...`);
543
+ const driveIds = driveIdArg ? [driveIdArg] : await fetchDrives(baseUrl);
544
+ console.log(`Found ${driveIds.length} drive(s): ${driveIds.join(", ")}`);
545
+ let drivesProcessed = 0;
546
+ let drivesFailed = 0;
547
+ const driveFailures = [];
548
+ for (let i = 0; i < driveIds.length; i++) {
549
+ if (i > 0)
550
+ await sleep(REQUEST_DELAY_MS);
551
+ const driveId = driveIds[i];
552
+ try {
553
+ await downloadDrive(baseUrl, driveId, outputBase);
554
+ drivesProcessed++;
555
+ }
556
+ catch (err) {
557
+ const reason = err instanceof Error ? err.message : String(err);
558
+ console.error(`\n${"=".repeat(60)}`);
559
+ console.error(`DRIVE: ${driveId} — FAILED`);
560
+ console.error(`${"=".repeat(60)}`);
561
+ console.error(` Reason: ${reason}`);
562
+ driveFailures.push({ id: driveId, reason });
563
+ drivesFailed++;
564
+ }
565
+ }
566
+ console.log(`\n${"=".repeat(60)}`);
567
+ console.log(`DONE`);
568
+ console.log(`${"=".repeat(60)}`);
569
+ console.log(` Output: ${outputBase}`);
570
+ console.log(` Drives processed: ${drivesProcessed}`);
571
+ console.log(` Drives skipped: ${drivesFailed}`);
572
+ if (driveFailures.length > 0) {
573
+ console.log(` Reasons for skipped drives:`);
574
+ for (const f of driveFailures) {
575
+ console.log(` - "${f.id}"`);
576
+ console.log(` ${f.reason}`);
577
+ }
578
+ }
579
+ }
580
+ main().catch((err) => {
581
+ console.error(err);
582
+ process.exit(1);
583
+ });
@@ -1,2 +1,19 @@
1
- export declare const requestDirectPayment: (invoiceData: any) => Promise<any>;
1
+ interface InvoicePaymentData {
2
+ buyerInfo: {
3
+ email: string;
4
+ [key: string]: unknown;
5
+ };
6
+ invoiceNumber?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export interface RequestFinanceResponse {
10
+ errors?: string[];
11
+ invoiceLinks?: {
12
+ pay: string;
13
+ };
14
+ id?: string;
15
+ [key: string]: unknown;
16
+ }
17
+ export declare const requestDirectPayment: (invoiceData: InvoicePaymentData | Record<string, unknown>) => Promise<RequestFinanceResponse>;
18
+ export {};
2
19
  //# sourceMappingURL=requestFinance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"requestFinance.d.ts","sourceRoot":"","sources":["../../../scripts/invoice/requestFinance.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,GAAU,aAAa,GAAG,iBAiD1D,CAAC"}
1
+ {"version":3,"file":"requestFinance.d.ts","sourceRoot":"","sources":["../../../scripts/invoice/requestFinance.ts"],"names":[],"mappings":"AAMA,UAAU,kBAAkB;IAC1B,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,oBAAoB,GAC/B,aAAa,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACxD,OAAO,CAAC,sBAAsB,CA0DhC,CAAC"}
@@ -3,8 +3,9 @@ const API_URL = "https://api.request.finance/invoices";
3
3
  const API_KEY = process.env.REQUEST_FINANCE_API_KEY; // Store in .env file
4
4
  const REQUEST_FINANCE_EMAIL = process.env.REQUEST_FINANCE_EMAIL;
5
5
  export const requestDirectPayment = async (invoiceData) => {
6
- invoiceData.buyerInfo.email = REQUEST_FINANCE_EMAIL;
7
- console.log("Getting a request to create an invoice", invoiceData.invoiceNumber);
6
+ const data = invoiceData;
7
+ data.buyerInfo.email = REQUEST_FINANCE_EMAIL ?? "";
8
+ console.log("Getting a request to create an invoice", data.invoiceNumber);
8
9
  try {
9
10
  // First API call to create the invoice
10
11
  const response = await axios.post(API_URL, invoiceData, {
@@ -30,11 +31,22 @@ export const requestDirectPayment = async (invoiceData) => {
30
31
  }
31
32
  catch (error) {
32
33
  console.error("Server: Error making invoice on-chain:", error);
33
- return error;
34
+ if (axios.isAxiosError(error) && error.response) {
35
+ return error.response.data;
36
+ }
37
+ return {
38
+ errors: [error instanceof Error ? error.message : "Unknown error"],
39
+ };
34
40
  }
35
41
  }
36
42
  catch (error) {
37
- console.error("Error creating invoice: error.response", error.response.data);
38
- return error.response.data;
43
+ if (axios.isAxiosError(error) && error.response) {
44
+ console.error("Error creating invoice: error.response", error.response.data);
45
+ return error.response.data;
46
+ }
47
+ console.error("Error creating invoice:", error);
48
+ return {
49
+ errors: [error instanceof Error ? error.message : "Unknown error"],
50
+ };
39
51
  }
40
52
  };
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Upload local .phd documents to a Powerhouse switchboard.
4
+ *
5
+ * Works with ANY document type — reads header.json and operations.json from
6
+ * the .phd file, auto-detects the document type, creates a new document via
7
+ * the matching _createDocument mutation, then replays all operations via
8
+ * pushUpdates on the drive endpoint.
9
+ *
10
+ * REQUIRES: Bun runtime (https://bun.sh)
11
+ *
12
+ * Usage:
13
+ * bun scripts/upload-phd-documents/upload-phd-documents.ts <switchboard-url> <drive-id> <file.phd> [file2.phd ...]
14
+ *
15
+ * Examples:
16
+ * bun scripts/upload-phd-documents/upload-phd-documents.ts http://localhost:4001 preview-f80015b9 "op hub.phd" "oh service.phd"
17
+ * bun scripts/upload-phd-documents/upload-phd-documents.ts http://localhost:4001 preview-f80015b9 invoice.phd
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=upload-phd-documents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-phd-documents.d.ts","sourceRoot":"","sources":["../../../scripts/upload-phd-documents/upload-phd-documents.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG"}