@powerhousedao/builder-profile 0.0.11 → 0.0.12

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 (62) hide show
  1. package/dist/document-models/builder-profile/actions.d.ts.map +1 -1
  2. package/dist/document-models/builder-profile/gen/builders/actions.d.ts +1 -1
  3. package/dist/document-models/builder-profile/gen/builders/actions.d.ts.map +1 -1
  4. package/dist/document-models/builder-profile/gen/builders/actions.js +1 -1
  5. package/dist/document-models/builder-profile/gen/builders/operations.d.ts +2 -2
  6. package/dist/document-models/builder-profile/gen/builders/operations.d.ts.map +1 -1
  7. package/dist/document-models/builder-profile/gen/builders/operations.js +0 -2
  8. package/dist/document-models/builder-profile/gen/document-model.js +5 -5
  9. package/dist/document-models/builder-profile/gen/document-schema.d.ts +54 -379
  10. package/dist/document-models/builder-profile/gen/document-schema.d.ts.map +1 -1
  11. package/dist/document-models/builder-profile/gen/ph-factories.d.ts.map +1 -1
  12. package/dist/document-models/builder-profile/gen/ph-factories.js +0 -1
  13. package/dist/document-models/builder-profile/gen/reducer.d.ts.map +1 -1
  14. package/dist/document-models/builder-profile/gen/reducer.js +22 -11
  15. package/dist/document-models/builder-profile/gen/schema/types.d.ts +21 -13
  16. package/dist/document-models/builder-profile/gen/schema/types.d.ts.map +1 -1
  17. package/dist/document-models/builder-profile/gen/schema/zod.d.ts +59 -11
  18. package/dist/document-models/builder-profile/gen/schema/zod.d.ts.map +1 -1
  19. package/dist/document-models/builder-profile/gen/schema/zod.js +17 -21
  20. package/dist/document-models/builder-profile/gen/types.d.ts.map +1 -1
  21. package/dist/document-models/builder-profile/gen/utils.d.ts.map +1 -1
  22. package/dist/document-models/builder-profile/gen/utils.js +0 -1
  23. package/dist/document-models/builder-profile/hooks.d.ts +5 -2
  24. package/dist/document-models/builder-profile/hooks.d.ts.map +1 -1
  25. package/dist/document-models/builder-profile/hooks.js +3 -4
  26. package/dist/document-models/builder-profile/index.d.ts +0 -4
  27. package/dist/document-models/builder-profile/index.d.ts.map +1 -1
  28. package/dist/document-models/builder-profile/index.js +0 -4
  29. package/dist/document-models/builder-profile/module.d.ts.map +1 -1
  30. package/dist/document-models/builder-profile/module.js +1 -0
  31. package/dist/document-models/builder-profile/src/reducers/builders.d.ts.map +1 -1
  32. package/dist/document-models/builder-profile/src/reducers/builders.js +0 -2
  33. package/dist/document-models/builder-profile/tests/builders.test.d.ts +2 -0
  34. package/dist/document-models/builder-profile/tests/builders.test.d.ts.map +1 -0
  35. package/dist/document-models/builder-profile/tests/builders.test.js +115 -0
  36. package/dist/document-models/builder-profile/tests/document-model.test.d.ts +10 -0
  37. package/dist/document-models/builder-profile/tests/document-model.test.d.ts.map +1 -0
  38. package/dist/document-models/builder-profile/tests/document-model.test.js +104 -0
  39. package/dist/document-models/document-models.d.ts.map +1 -1
  40. package/dist/document-models/document-models.js +1 -3
  41. package/dist/editors/builder-profile/components/ContributorsSection.d.ts.map +1 -1
  42. package/dist/editors/builder-profile/components/ContributorsSection.js +15 -1
  43. package/dist/editors/builder-profile/components/ProfilePreview.d.ts.map +1 -1
  44. package/dist/editors/builder-profile/components/ProfilePreview.js +2 -2
  45. package/dist/editors/builder-profile/editor.d.ts.map +1 -1
  46. package/dist/editors/builder-profile/editor.js +147 -48
  47. package/dist/editors/builder-profile/module.d.ts +1 -1
  48. package/dist/editors/builder-profile/module.d.ts.map +1 -1
  49. package/dist/editors/builder-profile/module.js +1 -1
  50. package/dist/index.d.ts +2 -2
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +2 -4
  53. package/dist/scripts/builder-migration/migrate_builders.d.ts +18 -0
  54. package/dist/scripts/builder-migration/migrate_builders.d.ts.map +1 -0
  55. package/dist/scripts/builder-migration/migrate_builders.js +405 -0
  56. package/dist/style.css +120 -29
  57. package/dist/subgraphs/builder-profile/schema.d.ts.map +1 -1
  58. package/dist/subgraphs/builder-profile/schema.js +0 -1
  59. package/package.json +31 -26
  60. package/dist/vitest.config.d.ts +0 -3
  61. package/dist/vitest.config.d.ts.map +0 -1
  62. package/dist/vitest.config.js +0 -8
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Manifest } from "document-model";
2
+ export { documentModels } from "./document-models/document-models.js";
3
+ export { editors } from "./editors/editors.js";
2
4
  export declare const manifest: Manifest;
3
- export declare const documentModels: import("document-model").DocumentModelModule<import("./document-models/builder-profile/index.js").BuilderProfilePHState>[];
4
- export declare const editors: import("document-model").EditorModule[];
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK/C,eAAO,MAAM,QAAQ,EAAE,QAAuB,CAAC;AAC/C,eAAO,MAAM,cAAc,4HAAuC,CAAC;AACnE,eAAO,MAAM,OAAO,yCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,eAAO,MAAM,QAAQ,EAAE,QAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,4 @@
1
1
  import manifestJson from "./powerhouse.manifest.json" with { type: "json" };
2
- import * as documentModelsExports from "./document-models/index.js";
3
- import * as editorsExports from "./editors/index.js";
2
+ export { documentModels } from "./document-models/document-models.js";
3
+ export { editors } from "./editors/editors.js";
4
4
  export const manifest = manifestJson;
5
- export const documentModels = Object.values(documentModelsExports);
6
- export const editors = Object.values(editorsExports);
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Builder Profile Migration Script
4
+ *
5
+ * Migrates all builder profile documents from a source drive (on one MCP endpoint)
6
+ * to a new "BuildersV2" drive (on another MCP endpoint).
7
+ *
8
+ * Usage:
9
+ * bun migrate_builders.ts <source-mcp-url> <source-drive-id> <target-mcp-url>
10
+ *
11
+ * Example:
12
+ * bun migrate_builders.ts \
13
+ * https://switchboard.powerhouse.xyz/mcp \
14
+ * source-drive-id \
15
+ * http://localhost:4001/mcp
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=migrate_builders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate_builders.d.ts","sourceRoot":"","sources":["../../../scripts/builder-migration/migrate_builders.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;GAcG"}
@@ -0,0 +1,405 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Builder Profile Migration Script
4
+ *
5
+ * Migrates all builder profile documents from a source drive (on one MCP endpoint)
6
+ * to a new "BuildersV2" drive (on another MCP endpoint).
7
+ *
8
+ * Usage:
9
+ * bun migrate_builders.ts <source-mcp-url> <source-drive-id> <target-mcp-url>
10
+ *
11
+ * Example:
12
+ * bun migrate_builders.ts \
13
+ * https://switchboard.powerhouse.xyz/mcp \
14
+ * source-drive-id \
15
+ * http://localhost:4001/mcp
16
+ */
17
+ // Parse command line arguments
18
+ const args = process.argv.slice(2);
19
+ if (args.length !== 3) {
20
+ console.error("Usage: bun migrate_builders.ts <source-mcp-url> <source-drive-id> <target-mcp-url>");
21
+ console.error("");
22
+ console.error("Example:");
23
+ console.error(" bun migrate_builders.ts \\");
24
+ console.error(" https://switchboard.powerhouse.xyz/mcp \\");
25
+ console.error(" source-drive-id \\");
26
+ console.error(" http://localhost:4001/mcp");
27
+ process.exit(1);
28
+ }
29
+ const [SOURCE_MCP_URL, SOURCE_DRIVE_ID, TARGET_MCP_URL] = args;
30
+ const TARGET_DRIVE_NAME = "BuildersV2";
31
+ const BUILDER_PROFILE_DOC_TYPE = "powerhouse/builder-profile";
32
+ let requestId = 1;
33
+ // Helper function to make MCP requests
34
+ async function mcpRequest(mcpUrl, payload) {
35
+ const response = await fetch(mcpUrl, {
36
+ method: "POST",
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ Accept: "application/json, text/event-stream",
40
+ },
41
+ body: JSON.stringify(payload),
42
+ });
43
+ const text = await response.text();
44
+ // Handle SSE format (event: message\ndata: {...})
45
+ if (text.includes("event: message")) {
46
+ const lines = text.split("\n");
47
+ const dataLine = lines.find((line) => line.startsWith("data: "));
48
+ if (dataLine) {
49
+ const jsonData = dataLine.substring(6);
50
+ return JSON.parse(jsonData);
51
+ }
52
+ throw new Error("No data line found in SSE response");
53
+ }
54
+ return JSON.parse(text);
55
+ }
56
+ // Get all drive IDs from target MCP
57
+ async function getTargetDriveIds() {
58
+ const payload = {
59
+ jsonrpc: "2.0",
60
+ method: "tools/call",
61
+ params: {
62
+ name: "getDrives",
63
+ arguments: {},
64
+ },
65
+ id: requestId++,
66
+ };
67
+ const response = await mcpRequest(TARGET_MCP_URL, payload);
68
+ if (response.error) {
69
+ throw new Error(`Failed to get drives: ${JSON.stringify(response.error)}`);
70
+ }
71
+ const result = response.result?.structuredContent;
72
+ return result?.driveIds || [];
73
+ }
74
+ // Create a new drive on target MCP
75
+ async function createTargetDrive(name) {
76
+ const payload = {
77
+ jsonrpc: "2.0",
78
+ method: "tools/call",
79
+ params: {
80
+ name: "addDrive",
81
+ arguments: {
82
+ driveInput: {
83
+ id: name,
84
+ slug: name,
85
+ global: {
86
+ name,
87
+ icon: null,
88
+ },
89
+ local: {
90
+ availableOffline: false,
91
+ sharingType: null,
92
+ },
93
+ },
94
+ },
95
+ },
96
+ id: requestId++,
97
+ };
98
+ const response = await mcpRequest(TARGET_MCP_URL, payload);
99
+ if (response.error) {
100
+ throw new Error(`Failed to create drive: ${JSON.stringify(response.error)}`);
101
+ }
102
+ // The drive ID will be the name we provided
103
+ const result = response.result?.structuredContent;
104
+ const driveId = result?.id || result?.drive?.id || name;
105
+ return driveId;
106
+ }
107
+ // Get document IDs from source drive
108
+ async function getSourceDocumentIds(driveId) {
109
+ const payload = {
110
+ jsonrpc: "2.0",
111
+ method: "tools/call",
112
+ params: {
113
+ name: "getDocuments",
114
+ arguments: { parentId: driveId },
115
+ },
116
+ id: requestId++,
117
+ };
118
+ const response = await mcpRequest(SOURCE_MCP_URL, payload);
119
+ if (response.error) {
120
+ throw new Error(`Failed to get documents: ${JSON.stringify(response.error)}`);
121
+ }
122
+ const result = response.result?.structuredContent;
123
+ return result?.documentIds || [];
124
+ }
125
+ // Get a specific document from source MCP
126
+ async function getSourceDocument(docId) {
127
+ const payload = {
128
+ jsonrpc: "2.0",
129
+ method: "tools/call",
130
+ params: {
131
+ name: "getDocument",
132
+ arguments: { id: docId },
133
+ },
134
+ id: requestId++,
135
+ };
136
+ const response = await mcpRequest(SOURCE_MCP_URL, payload);
137
+ if (response.error) {
138
+ throw new Error(`Failed to get document: ${JSON.stringify(response.error)}`);
139
+ }
140
+ const result = response.result?.structuredContent;
141
+ if (!result?.document) {
142
+ throw new Error(`No document returned for ID: ${docId}`);
143
+ }
144
+ return result.document;
145
+ }
146
+ // Create a new document on target MCP
147
+ async function createTargetDocument(documentType) {
148
+ const payload = {
149
+ jsonrpc: "2.0",
150
+ method: "tools/call",
151
+ params: {
152
+ name: "createDocument",
153
+ arguments: { documentType },
154
+ },
155
+ id: requestId++,
156
+ };
157
+ const response = await mcpRequest(TARGET_MCP_URL, payload);
158
+ if (response.error) {
159
+ throw new Error(`Failed to create document: ${JSON.stringify(response.error)}`);
160
+ }
161
+ // Try multiple possible response formats
162
+ const structured = response.result?.structuredContent;
163
+ const docId = structured?.id ||
164
+ structured?.documentId ||
165
+ structured?.document?.id ||
166
+ structured?.header?.id;
167
+ if (!docId || typeof docId !== "string") {
168
+ throw new Error("No document ID returned from createDocument");
169
+ }
170
+ return docId;
171
+ }
172
+ // Add actions to a document on target MCP
173
+ async function addTargetActions(documentId, actions) {
174
+ const payload = {
175
+ jsonrpc: "2.0",
176
+ method: "tools/call",
177
+ params: {
178
+ name: "addActions",
179
+ arguments: { documentId, actions },
180
+ },
181
+ id: requestId++,
182
+ };
183
+ const response = await mcpRequest(TARGET_MCP_URL, payload);
184
+ if (response.error) {
185
+ throw new Error(`Failed to add actions: ${JSON.stringify(response.error)}`);
186
+ }
187
+ }
188
+ // Generate actions to populate a builder profile from source state
189
+ function generateMigrationActions(sourceState) {
190
+ const actions = [];
191
+ // 1. Update basic profile information - always include this with all available data
192
+ const profileInput = {};
193
+ // Set defaults for required fields if missing from source
194
+ profileInput.type = sourceState.type || "INDIVIDUAL";
195
+ // Copy optional fields if they exist
196
+ if (sourceState.id)
197
+ profileInput.id = sourceState.id;
198
+ if (sourceState.code)
199
+ profileInput.code = sourceState.code;
200
+ if (sourceState.slug)
201
+ profileInput.slug = sourceState.slug;
202
+ if (sourceState.name)
203
+ profileInput.name = sourceState.name;
204
+ if (sourceState.icon)
205
+ profileInput.icon = sourceState.icon;
206
+ if (sourceState.description)
207
+ profileInput.description = sourceState.description;
208
+ if (sourceState.about)
209
+ profileInput.about = sourceState.about;
210
+ if (sourceState.status)
211
+ profileInput.status = sourceState.status;
212
+ // Always push UPDATE_PROFILE to set the basic data
213
+ actions.push({
214
+ type: "UPDATE_PROFILE",
215
+ scope: "global",
216
+ input: profileInput,
217
+ });
218
+ // 2. Set operator flag - default to false if undefined in source
219
+ const isOperator = sourceState.isOperator !== undefined && sourceState.isOperator !== null
220
+ ? sourceState.isOperator
221
+ : false;
222
+ actions.push({
223
+ type: "SET_OPERATOR",
224
+ scope: "global",
225
+ input: { isOperator },
226
+ });
227
+ // 3. Add skills
228
+ if (sourceState.skills && sourceState.skills.length > 0) {
229
+ sourceState.skills.forEach((skill) => {
230
+ actions.push({
231
+ type: "ADD_SKILL",
232
+ scope: "global",
233
+ input: { skill },
234
+ });
235
+ });
236
+ }
237
+ // 4. Add scopes
238
+ if (sourceState.scopes && sourceState.scopes.length > 0) {
239
+ sourceState.scopes.forEach((scope) => {
240
+ actions.push({
241
+ type: "ADD_SCOPE",
242
+ scope: "global",
243
+ input: { scope },
244
+ });
245
+ });
246
+ }
247
+ // 5. Add links
248
+ if (sourceState.links && sourceState.links.length > 0) {
249
+ sourceState.links.forEach((link) => {
250
+ actions.push({
251
+ type: "ADD_LINK",
252
+ scope: "global",
253
+ input: {
254
+ id: link.id,
255
+ url: link.url,
256
+ label: link.label || undefined,
257
+ },
258
+ });
259
+ });
260
+ }
261
+ // 6. Add contributors
262
+ if (sourceState.contributors && sourceState.contributors.length > 0) {
263
+ sourceState.contributors.forEach((contributorPHID) => {
264
+ actions.push({
265
+ type: "ADD_CONTRIBUTOR",
266
+ scope: "global",
267
+ input: { contributorPHID },
268
+ });
269
+ });
270
+ }
271
+ return actions;
272
+ }
273
+ // Main function
274
+ async function main() {
275
+ try {
276
+ console.log("=".repeat(70));
277
+ console.log("Builder Profile Migration Script");
278
+ console.log("=".repeat(70));
279
+ console.log("\nConfiguration:");
280
+ console.log(` Source MCP URL: ${SOURCE_MCP_URL}`);
281
+ console.log(` Source Drive ID: ${SOURCE_DRIVE_ID}`);
282
+ console.log(` Target MCP URL: ${TARGET_MCP_URL}`);
283
+ console.log(` Target Drive Name: ${TARGET_DRIVE_NAME}`);
284
+ console.log("");
285
+ // Step 1: Check if BuildersV2 drive exists on target MCP
286
+ console.log("Checking for existing drives on target MCP...");
287
+ const driveIds = await getTargetDriveIds();
288
+ console.log(`✓ Found ${driveIds.length} drives on target`);
289
+ let targetDriveId;
290
+ const existingDriveId = driveIds.find((id) => id === TARGET_DRIVE_NAME);
291
+ if (existingDriveId) {
292
+ console.log(`✓ Drive "${TARGET_DRIVE_NAME}" already exists`);
293
+ targetDriveId = existingDriveId;
294
+ }
295
+ else {
296
+ console.log(`Creating new drive "${TARGET_DRIVE_NAME}" on target MCP...`);
297
+ targetDriveId = await createTargetDrive(TARGET_DRIVE_NAME);
298
+ console.log(`✓ Created drive "${TARGET_DRIVE_NAME}" (ID: ${targetDriveId})`);
299
+ }
300
+ // Step 2: Get all document IDs from source drive
301
+ console.log(`\nFetching documents from source drive "${SOURCE_DRIVE_ID}" on source MCP...`);
302
+ const sourceDocIds = await getSourceDocumentIds(SOURCE_DRIVE_ID);
303
+ console.log(`✓ Found ${sourceDocIds.length} documents in source drive`);
304
+ if (sourceDocIds.length === 0) {
305
+ console.log("\n⚠ No documents found in source drive");
306
+ return;
307
+ }
308
+ // Step 3: Fetch each document and filter for builder profiles
309
+ console.log("\nFetching document details and filtering builder profiles...");
310
+ const builderProfileDocs = [];
311
+ for (const docId of sourceDocIds) {
312
+ try {
313
+ const doc = await getSourceDocument(docId);
314
+ if (doc.header.documentType === BUILDER_PROFILE_DOC_TYPE) {
315
+ builderProfileDocs.push({ id: docId, doc });
316
+ }
317
+ }
318
+ catch (error) {
319
+ console.log(` - Skipping ${docId}: ${error}`);
320
+ }
321
+ }
322
+ console.log(`✓ Found ${builderProfileDocs.length} builder profile documents`);
323
+ if (builderProfileDocs.length === 0) {
324
+ console.log("\n⚠ No builder profile documents found to migrate");
325
+ return;
326
+ }
327
+ // Step 4: Migrate each builder profile
328
+ console.log("\n" + "-".repeat(70));
329
+ console.log("Starting migration...");
330
+ console.log("-".repeat(70));
331
+ let successCount = 0;
332
+ let errorCount = 0;
333
+ for (let i = 0; i < builderProfileDocs.length; i++) {
334
+ const { id: sourceDocId, doc: sourceDoc } = builderProfileDocs[i];
335
+ const sourceState = sourceDoc.state.global;
336
+ console.log(`\n[${i + 1}/${builderProfileDocs.length}] Migrating: ${sourceState.name || sourceDocId}`);
337
+ try {
338
+ console.log(` - Name: ${sourceState.name || "(unnamed)"}`);
339
+ console.log(` - Type: ${sourceState.type}`);
340
+ console.log(` - Status: ${sourceState.status || "(no status)"}`);
341
+ console.log(` - Is Operator: ${sourceState.isOperator}`);
342
+ console.log(` - Skills: ${sourceState.skills?.length || 0}`);
343
+ console.log(` - Scopes: ${sourceState.scopes?.length || 0}`);
344
+ console.log(` - Links: ${sourceState.links?.length || 0}`);
345
+ console.log(` - Contributors: ${sourceState.contributors?.length || 0}`);
346
+ // Create new document on target MCP
347
+ const newDocId = await createTargetDocument(BUILDER_PROFILE_DOC_TYPE);
348
+ console.log(` ✓ Created new document on target: ${newDocId}`);
349
+ // Add document to target drive
350
+ await addTargetActions(targetDriveId, [
351
+ {
352
+ type: "ADD_FILE",
353
+ scope: "global",
354
+ input: {
355
+ id: newDocId,
356
+ name: sourceState.name || "Untitled Builder",
357
+ documentType: BUILDER_PROFILE_DOC_TYPE,
358
+ },
359
+ },
360
+ ]);
361
+ console.log(` ✓ Added to drive "${TARGET_DRIVE_NAME}"`);
362
+ // Generate and apply migration actions to target document
363
+ const migrationActions = generateMigrationActions(sourceState);
364
+ console.log(` - Generated ${migrationActions.length} actions`);
365
+ if (migrationActions.length > 0) {
366
+ // Send actions in batches of 20
367
+ const BATCH_SIZE = 20;
368
+ for (let j = 0; j < migrationActions.length; j += BATCH_SIZE) {
369
+ const batch = migrationActions.slice(j, j + BATCH_SIZE);
370
+ await addTargetActions(newDocId, batch);
371
+ }
372
+ console.log(` ✓ Applied all migration actions`);
373
+ }
374
+ successCount++;
375
+ console.log(` ✓ Migration complete for "${sourceState.name || sourceDocId}"`);
376
+ }
377
+ catch (error) {
378
+ errorCount++;
379
+ console.error(` ✗ Error migrating document: ${error}`);
380
+ }
381
+ }
382
+ // Summary
383
+ console.log("\n" + "=".repeat(70));
384
+ console.log("Migration Summary");
385
+ console.log("=".repeat(70));
386
+ console.log(` Total documents found: ${builderProfileDocs.length}`);
387
+ console.log(` Successfully migrated: ${successCount}`);
388
+ console.log(` Errors: ${errorCount}`);
389
+ console.log(` Target drive: ${TARGET_DRIVE_NAME} (${targetDriveId})`);
390
+ console.log("=".repeat(70));
391
+ if (errorCount === 0) {
392
+ console.log("\n✓ Migration completed successfully!");
393
+ }
394
+ else {
395
+ console.log(`\n⚠ Migration completed with ${errorCount} error(s)`);
396
+ }
397
+ }
398
+ catch (error) {
399
+ console.error("\n✗ Fatal error:", error);
400
+ process.exit(1);
401
+ }
402
+ }
403
+ // Run the script
404
+ main();
405
+ export {};